f# - Delegate/Func conversion and misleading compiler error message -


i thought conversions between f# functions , system.func had done manually, there appears case compiler (sometimes) you. , when goes wrong error message isn't accurate:

module foo =     let dict = new system.collections.generic.dictionary<string, system.func<obj,obj>>()      let f (x:obj) = x              // question 1: why compile without explicit type conversion?         dict.["foo"] <- fun (x:obj) -> x          // question 2: given above line compiles, why fail?         dict.["bar"] <- f  

the last line fails compile, , error is:

this expression expected have type     system.func<obj,obj>     here has type     'a -> obj 

clearly function f doesn't have signature of 'a > obj. if f# 3.1 compiler happy first dictionary assignment, why not second?

the part of spec should explain 8.13.7 type directed conversions @ member invocations. in short, when invoking member, automatic conversion f# function delegate applied. unfortunately, spec bit unclear; wording seems conversion might apply function expression, in practice appears apply anonymous function expressions.

the spec bit out of date; in f# 3.0 type directed conversions enable conversion system.linq.expressions.expression<somedelegatetype>.

edit

in looking @ past correspondence f# team, think i've tracked down how conversion applied non-syntactic function expression. i'll include here completeness, it's bit of strange corner case, purposes should consider rule syntactic functions have type directed conversion applied.

the exception overload resolution can result in converting arbitrary expression of function type; partly explained section 14.4 method application resolution, although it's pretty dense , still not entirely clear. basically, argument expressions elaborated when there multiple overloads; when there's single candidate method, argument types asserted against unelaborated arguments (note: it's not obvious should matter in terms of whether conversion applicable, matter empirically). here's example demonstrating exception:

type t =     static member m(i:int) = "first overload"     static member m(f:system.func<int,int>) = "second overload"  let f = + 1  t.m f |> printfn "%s"  

Comments

Popular posts from this blog

android - Get AccessToken using signpost OAuth without opening a browser (Two legged Oauth) -

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: mockito -

google shop client API returns 400 bad request error while adding an item -