I have module like this
module CommonModule
let addFive x =
x+5
let multiFive x =
x*5
And I would like to list methods of this module by reflection.
I found this: Can you list the contents of a namespace or module in F#, but I don't know how to use it.
I'm new in F#.
Please help
I think the only way to do this is to declare a type inside the module, then use reflection to get the DeclaringType and call GetMethods on that:
open System.Reflection
module CommonModule =
type Marker = interface end
let f x = x * x
typeof<CommonModule.Marker>.DeclaringType.GetMethods()
This will give you a MethodInfo [] containing f and the methods inherited from System.Object:
[|Int32 f(Int32); System.String ToString(); Boolean Equals(System.Object);
Int32 GetHashCode(); System.Type GetType()|]
EDIT (responding to lukaszb's comment)
If you want to look up the module by name, you'll need to get the assembly first, then find the module type within the assembly and call GetMethods. To do this for the previous example, you would add the following code:
// Get the assembly somehow (by name, by GetEntryAssembly, etc)
let assembly = Assembly.GetExecutingAssembly()
// Retrieve the methods (including F# functions) on the module type
let functions =
match assembly.GetTypes() |> Array.tryFind (fun t -> t.Name = "CommonModule") with
| Some moduleType -> moduleType.GetMethods()
| None -> [||]
// Find the function you want
match functions |> Array.tryFind (fun f -> f.Name = "f") with
| Some f -> f.Invoke(null, [|2|]) // Invoke the function
| None -> failwith "Function `f` not found"
One benefit of doing it this way is that you no longer need the Marker type in the module.
Related
This code snippet reproduces a problem I am having with some production code. The function containsProperty represents a real world function that is actually in a library, so that I have no say in what the signature is.
The problem is that I can't figure out how to create a wrapper function that can take a normal function as argument, and then pass that on to containsProperty. I can call containsProperty directly with a function as a lambda expression, but I can't call it with a function that comes from some other source.
The function addToGroup is the best I've come up with so far, and it uses quotations. There are two problems with that approach, which I am trying to figure out. First, how do I get rid of the Func cast in the quotation? Perhaps somehow move it into addToGroup? Second, can I build on this in order to just pass a function? I haven't succeeded in finding something that doesn't produce either a compile time error or a runtime error.
The function addToGroup2 is what I'd like to do, but it doesn't compile. The error message is "No constructors are available for the type 'Quotations.Expr<'a>'".
Why do I bother to struggle with this? Because as long as I can't treat the passed in function as a first class value, I can't create the design I'm after. I want these functions to come along from a collection of records.
If you paste this snippet into LINQPad or something, comment out addToGroup2 and the calls to it, in order to make the snippet compile and run.
open System
open System.ComponentModel
open System.ComponentModel.DataAnnotations // Reference to this assembly required.
type CfgSettings = {
mutable ConnectionString: string
mutable Port: int
}
and CfgSettingsMetadata() =
static member containsProperty<'TProperty>(propertyExpression: Linq.Expressions.Expression<Func<CfgSettings,'TProperty>>) =
Console.WriteLine "good!"
static member addToGroup f =
CfgSettingsMetadata.containsProperty(FSharp.Linq.RuntimeHelpers.LeafExpressionConverter.QuotationToLambdaExpression f) |> ignore
static member addToGroup2 (f: CfgSettings -> 'TProperty) =
CfgSettingsMetadata.containsProperty(FSharp.Linq.RuntimeHelpers.LeafExpressionConverter.QuotationToLambdaExpression (Quotations.Expr<Func<CfgSettings,'TProperty>>f)) |> ignore
static member BuildMetadata () =
CfgSettingsMetadata.containsProperty(fun x -> x.ConnectionString)
CfgSettingsMetadata.containsProperty(fun x -> x.Port)
CfgSettingsMetadata.addToGroup <# Func<_,_>(fun x -> x.ConnectionString) #>
CfgSettingsMetadata.addToGroup <# Func<_,_>(fun x -> x.Port) #>
CfgSettingsMetadata.addToGroup2 (fun x -> x.ConnectionString)
CfgSettingsMetadata.addToGroup2 (fun x -> x.Port)
CfgSettingsMetadata.BuildMetadata()
Both answers in question Expression<Func<T, bool>> from a F# func helped me somewhat, but I haven't found a solution yet.
So, there are two questions here.
How to pass a function without having to wrap it in <# ... #>?
For this, you just need to add the [<ReflectedDefinition>] attribute to your method's parameter. It implicitly wraps the argument passed to it in a quotation.
type CfgSettingsMetadata() =
static member addToGroup([<ReflectedDefinition>] f: Expr<CfgSettings -> 'TProperty>) =
CfgSettingsMetadata.containsProperty(LeafExpressionConverter.QuotationToLambdaExpression f) |> ignore
// Example use:
CfgSettingsMetadata.addToGroup(Func<_, _>(fun x -> x.ConnectionString))
How to convert from Expr<a -> b> to Expression<Func<a, b>>?
This is indeed explained in the question you linked, although the API has changed a bit since then.
type CfgSettingsMetadata() =
static member addToGroup ([<ReflectedDefinition>] (f: Expr<CfgSettings -> 'TProperty>)) =
let call = LeafExpressionConverter.QuotationToExpression f :?> MethodCallExpression
let lambda = call.Arguments.[0] :?> LambdaExpression
let e = Expression.Lambda<Func<CfgSettings, 'TProperty>>(lambda.Body, lambda.Parameters)
CfgSettingsMetadata.containsProperty(e) |> ignore
// Example use:
CfgSettingsMetadata.addToGroup(fun x -> x.ConnectionString)
Not entirely sure the title describes it ok, but I do have about the following code:
paket.dependencies:
source https://www.nuget.org/api/v2
nuget fsharpx.extras
nuget mongodb.driver
some.fsx:
#r #".\packages\MongoDB.Bson\lib\net45\MongoDB.Bson.dll"
#r #".\packages\MongoDB.Driver\lib\net45\MongoDB.Driver.dll"
#r #".\packages\MongoDB.Driver.Core\lib\net45\MongoDB.Driver.Core.dll"
#r #".\packages\FSharpX.Extras\lib\net45\FSharpX.Extras.dll"
open MongoDB
open MongoDB.Driver
open MongoDB.Bson
open MongoDB.Bson.Serialization
open FSharpx.Choice
let private createClient (connectString:string) = MongoClient(connectString)
let CreateClient = protect createClient
let private getDb name (client:IMongoClient) = client.GetDatabase(name)
let GetDB1 name client =
choose {
let! c = client
return! (protect (getDb name) c)
}
let GetDB2 name (client:Choice<IMongoClient, exn>) =
protect (getDb name)
<!> client
The point for this "excersise" was to write GetDB2 so that it does the same as GetDB1 but use operators (applicatives?), but I am at the moment not able to turn my head to manage this.
The above code compiles, but the signatures for
GetDB1 and GetDB2 are not equal, and Im obviously doing something not right.
val GetDB1 :
name:string ->
client:Choice<#MongoDB.Driver.IMongoClient,exn> ->
Choice<MongoDB.Driver.IMongoDatabase,exn>
val GetDB2 :
name:string ->
client:Choice<MongoDB.Driver.IMongoClient,exn> ->
Choice<Choice<MongoDB.Driver.IMongoDatabase,exn>,exn>
I have tried several versions and orders of doing things in GetDB2 but I more or less always end at same signature as above.
The general idea I initially had was to write small function doing the stuff they should and then add exception handling (protect) and then "wrap" and "unwrap" accordingly.
That might of course not be entirely right idea too.
Are someone able to point me in some directions here for further studies, code examples or anything? Any comments of any type are in fact welcome at this point ;-)
FSharpx doc
Addendum
I think the following should be about same as above, but without the mongodb dependencies.
#r #".\packages\FSharpX.Extras\lib\net45\FSharpX.Extras.dll"
type DataBase =
{
Name: string
}
type Client =
{
connectString: string
} with member this.GetDatabase name = {
Name = name
}
open FSharpx.Choice
let private createClient (connectString:string) = {
connectString= connectString
}
let CreateClient = protect createClient
let private getDb name (client:Client) = client.GetDatabase name
let GetDB1 name client =
choose {
let! c = client
return! (protect (getDb name) c)
}
let GetDB2 name client =
protect (getDb name)
<!> client
You are getting the compounding of types here because you have used the <!> operator, which is map. That is defined something like this:
let map f = function
| Choice1Of2 value = Choice1Of2 (f value)
| Choice2Of2 fail = Choice2Of2 fail
This has the signature ('T -> 'U) -> Choice<'T,'Failure> -> Choice<'U,'Failure>, i.e. the function f is used as a map inside the choice type. For example:
map (sprintf "%d")
has type Choice<int, 'Failure> -> Choice<string, 'Failure>. This is good for applying functions which do not use the Choice type - there is only one possible point of failure, and that happened before the call to map.
Your next function, however, produces a Choice type, but it takes a non-Choice type. This means that you want the errors to propagate through - if there is an error in the value, then choose that. If the value is fine, but there's an error in the function, then use that. If everything is successful, use that. This requires the two error types to be the same, which for you they are (exn).
This is describing the bind operation, defined like this:
let bind f = function
| Choice1Of2 value = f value
| Choice2Of2 fail = Choice2Of2 fail
with signature ('T -> Choice<'U,'Failure>) -> Choice<'T,'Failure> -> Choice<'U,'Failure>.
Note that bind is very similar to map, except that the latter raises the result into a Choice1Of2 - the mapped function is always successful.
In FSharpX, you can access bind by the |>-like operator >>=, or the <|-like operator <<=.
Finally, protect is a fancy way of catching a thrown exception into a Choice2Of2 exn. It is similar to map in that the passed function is of type 'T -> 'U, but the function can also throw an exception and the passed type is not a Choice. protect is defined something like this:
let protect f x =
try
Choice1Of2 (f x)
with
exn -> Choice2Of2 exn
so its signature is ('T -> 'U) -> 'T -> Choice<'U, exn>.
For more information on how everything is implemented, see the source of this computation expression.
Putting this all together, we can see why your example went wrong.
getDb name is a function Client -> DataBase
protect (getDb name) is a function Client -> Choice<DataBase, exn>
map (protect (getDb name)) is therefore a function Choice<Client, exn> -> Choice<Choice<DataBase, exn>, 'Failure>, because map works inside Choice.
What you want, though, is
let GetDB name client =
bind (protect (getDb name)) client
or in operator form,
let GetDB name client = client >>= protect (getDb name)
In general, if your mapping function has signature 'T -> 'U you want map. If it has 'T -> Choice<'U, 'Failure>, you want bind.
New to F#
Have a list of objects.
Objects share the same base class, but the timestamp attribute we want to order by is not present on the base class.
Every object in the list will have the timestamp attribute.
Requirement is to order the objects by the timestamp descending.
Attempted
let sortedList = unsortedList.Sort();
This results in
System.InvalidOperationException: Failed to compare two elements in
the array. ---> System.ArgumentException: At least one object must
implement IComparable. at System.Collections.Comparer.Compare(Object
a, Object b)
You didn't post code so I can't give you the exact code to solve it.
Typically you will have a property in the Base Class or alternatively in an Interface, but let's suppose you have this:
type A() = class end
type B(x) =
inherit A()
member val timestamp = x with get, set
type C(x) =
inherit A()
member val timestamp = x with get, set
let lst = [ new B(5) :> A ; new C(15) :> A; new B(4) :> A ;]
And you can't touch that code. Then what you can do is this:
let getTimeStamp (x:A) =
match x with
| :? B as x -> x.timestamp
| :? C as x -> x.timestamp
| _ -> failwith "subtype not handled"
lst |> List.sortBy (fun x -> -getTimeStamp x)
Using reflection is another possibility (see Mau's answer).
If you post a code sample I can give you a more specific solution and test it.
You can access the timestamp property using the dynamic operator ? as shown here:
C#'s 'dynamic' in F#
I want to extend one of the existing "core" modules, like Core.Option:
module Microsoft.FSharp.Core.Option
let filter predicate op =
match op with
| Some(v) -> if predicate(v) then Some(v) else None
| None -> None
(I know about bind function, but I think filter method for options in some case is more convenient).
But unfortunetely I can't use filter method without explicitely open Microsoft.FSharp.Core namespace:
// Commenting following line will break the code!
open Microsoft.FSharp.Core
let v1 = Some 42
let v2 = v1 |> Option.filter (fun v -> v > 40)
printfn "v2 is: %A" v2
In most cases we can't use functions from module without opening appropriate namespace.
F# compiler "opens" some predefine (core) namespace automatically (like Microsoft.FSharp.Core), this will not bring into the scope methods from "module extensions" and we still should open core namespaces manually.
My question is: Is there any workarounds?
Or the best way to extend "core" modules is to create such extensions in custom namespace and open this namespace manually?
// Lets custom Option module in our custom namespace
module CustomNamespace.Option
let filter predicate op = ...
// On the client side lets open our custom namespace.
// After that we can use both Option modules simultaneously!
open CustomNamespace
let v1 = Some 42
let b =
v1 |> Option.filter (fun v -> v > 40) // using CustomNamespace.Option
|> Option.isSome // using Microsoft.FSharp.Core.Option
For production code I would do what the Taha's answer suggests: create your own module and open/alias it as necessary. Most of your life as programmer will be spent reading code. It can be quite frustrating reading F# code where it is not clear where methods come from.
That being said, I was surprised to find that this works:
namespace Microsoft.FSharp.Core
module Option =
let filter predicate op =
match op with
| Some(v) -> if predicate(v) then Some(v) else None
| None -> None
namespace USERCODE
module Option = Microsoft.FSharp.Core.Option
module M =
let test () =
Some 1
|> Option.filter (fun x -> x > 0)
|> Option.map (fun x -> x + 1)
It does not remove the need to write something in the head of your files, but it does work around needing to open a namespace. Not relevant for Microsoft.FSharp.Core as it is always open by default, but helpful for other namespaces.
In order to extend an F# module create another with the same name:
module Option =
let filter predicate op =
match op with
| Some v -> match predicate v with true -> Some v | false -> None
| None -> None
let v1 = Some 42
let v2 = v1 |> Option.filter (fun v -> v > 40)
printfn "v2 is: %A" v2
Does it help if you add the AutoOpen attribute to the module?
[<AutoOpen>]
module Microsoft.FSharp.Core.Option
let filter predicate op =
match op with
| Some(v) -> if predicate(v) then Some(v) else None
| None -> None
EDIT
This works, but only across assembly borders. It doesn't work within the same assembly:
namespace Microsoft.FSharp.Core
module Option =
let filter predicate op =
match op with
| Some(v) -> if predicate(v) then Some(v) else None
| None -> None
[<assembly:AutoOpen("Microsoft.FSharp.Core")>]
do ()
To call it from another assembly:
[<EntryPoint>]
let main args =
let f () = Some "" |> Option.filter (fun f -> true)
Console.WriteLine("Hello world!")
0
According to the docs something like this should work in extending a type. However I must have got something wrong as it won't compile and gives. the following error:
One or more of the declared type parameters for this type extension
have a missing or wrong type constraint not matching the original type
constraints on 'Option<_>'F# Compiler(957)
open System.Runtime.CompilerServices
[<Extension>]
type Option with
[<Extension>]
static member fromBool predicate word =
if predicate word
then Some word
else None
This isn't a functioning answer more an addendum to the original question. Not sure if it is worth opening a new thread?
I am reading Web cloud and mobile solution with F# and I try to follow the web site the author is building. But I have some problem, I am unable to solve. I understand the logic of what I am doing , but it looks like some piece of code is missing to make it work .I have read up to page 19.
I have the following repository module :
module Repository =
let get (source : IQueryable<_>) queryFn=
queryFn |> Seq.toList
let getAll ()=
fun s -> query { for x in s do
select x }
The idea is to use getAll in queryFn to get all items from source. But I have a cast problem between the two .
Here is the controller that makes use of it:
[<HandleError>]
type GuitarsController(context : IDisposable, ?repository ) =
inherit Controller()
let fromRepository =
match repository with
| Some v -> v
| _ -> (context :?> FsMvcAppEntities).guitars
|> Repository.get
new() = new GuitarsController(new FsMvcAppEntities())
member this.Index() =
getAll()
|> fromRepository
|> this.View
getAll() does not go well with |> fromRepository.
The type ''b -> Linq.IQueryable<'c>' is not compatible with the type
'seq<'a>'.
When looking at the type defined in the repository module I can see that queryFn is :
val get : source:IQueryable<'a> -> queryFn:seq<'b> -> 'b list
and the getall gives
unit -> s:System.Linq.IQueryable<'a> -> System.Linq.IQueryable<'a>
Your Repository.get makes no use of source :D.
Change it to:
module Repository =
let get (source : IQueryable<_>) queryFn =
queryFn source |> Seq.toList