18

I'm working with an api that requires a value of type Func. (Specifically, I'm trying to call ModelMetadataProviders.Current.GetMetadataForType().

How can I construct that value in F#?

Christopher Bennage
  • 2,578
  • 2
  • 22
  • 32

3 Answers3

28

When calling a method that takes any delegate of the Func you shouldn't need to explicitly create the delegate, because F# implicitly converts lambda expressions to delegate type (in member calls). I think that just calling the method with lambda function should work (if it doesn't, could you share the error message?)

Here is a simple example that demonstrates this:

type Foo() = 
  member x.Bar(a:System.Func<obj>) = a.Invoke()

let f = Foo()
let rnd = f.Bar(fun () -> new Random() :> obj)

In your case, I suppose something like this should work:

m.GetMetadataForType((fun () -> <expression> :> obj), modelType)

Note that you need explicit upcast (expr :> obj), to make sure the lambda function returns the right type (obj). If you want to assign the lambda function to a local value using let, then it won't work, because implicit conversion works only when it is passed as an argument directly. However, in that case, it makes the code a bit nicer.

Tomas Petricek
  • 240,744
  • 19
  • 378
  • 553
  • I think there's a typo in your example, since `Bar` takes a `Func` but you're passing an implicit `Func`. – kvb Jul 13 '10 at 16:40
  • You are correct. Thanks Tomas. In my case, I didn't even need the cast. My original problem was that I did this: let acc = (fun()-> model) let meta = m.GetMetadataForType( acc, t) which doesn't convert, switching to this: let meta = m.GetMetadataForType( (fun()-> model), t) worked fine. – Christopher Bennage Jul 15 '10 at 14:26
  • One thing that just tripped me up. The implicit conversion only works if you have the System namespace open. This might seem (and probably is) obvious, but if you don't the error message you get isn't that helpful. – tonyj444 Feb 09 '18 at 16:40
8

You can normally pass in any () -> obj and it will be automatically converted to Func<obj>. You may need to wrap your fun with Func<obj>:

> let d : Func<obj> = Func<obj>(fun () -> box "hello");;

val d : Func<obj>
Tim Robinson
  • 53,480
  • 10
  • 121
  • 138
2
let f = new System.Func<obj>(fun() -> printfn "ok"; new obj())
Brian
  • 117,631
  • 17
  • 236
  • 300