Reputation: 2807
I'm experimenting with inline and operators....not a specific application.
based on reading things like http://nut-cracker.azurewebsites.net/blog/2011/11/15/typeclasses-for-fsharp/ but not understanding it.
so.
I can make
type HelperType = HelperType with
static member (=>) (d:HelperType,x: list<char>) = fun y -> x @ y
static member (=>) (d:HelperType,x:array<char>) = fun y -> Array.append x y
static member (=>) (d:HelperType,x:string ) = fun y -> x + y
let inline append x = HelperType => x
let x1 = append "" ""
let x1 = append [|'a'|] [|'b'|]
work...and sort of understand whats going on.
but lets try to overload of just the types rather than the values...so I go...
type TypeOf<'t> = | TypeOf
type HelperType = HelperType with
static member (<*>) (d:HelperType,x:TypeOf<list<char>> ) = fun x y -> x @ y
static member (<*>) (d:HelperType,x:TypeOf<array<char>> ) = fun x y -> Array.append x y
i.e. I don't actually need a value of the type just some proxy type value
and I go
let inline append2 (x : ^t) = (HelperType <*> (TypeOf :> TypeOf< ^t>)) x
and I get...
Error A unique overload for method 'op_LessMultiplyGreater' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: static member HelperType.( <*> ) : d:HelperType * x:TypeOf<char array> -> ('a0 [] -> 'a0 [] -> 'a0 []), static member HelperType.( <*> ) : d:HelperType * x:TypeOf<char list> -> ('a0 list -> 'a0 list -> 'a0 list)
but whats the difference here between the first working example and the second one?
Upvotes: 2
Views: 83
Reputation: 26204
The main difference between both append functions is that the second one knows the type to resolve, it would be TypeOf
of 'something', it just don't know 'something', but the append
in the first example has no clue to which type it would resolve so it defers the overload resolution to the calling site.
So the second example attempts to do the overload resolution and fails.
UPDATE
You might be interested in something like this:
type HelperType = HelperType with
static member (<*>) (d:HelperType, _:list<char> ) = fun (x:list<char>) y -> x @ y
static member (<*>) (d:HelperType, _:array<char>) = fun (x:array<char>) y -> Array.append x y
let inline append2 x y :'T = (HelperType <*> Unchecked.defaultof<'T>) x y
But it will need to know the return type in advance:
let x1 : array<char> = append2 [|'a'|] [|'b'|]
or you can change it as you already figured out:
let inline append2 (x:'T) y :'T = (HelperType <*> Unchecked.defaultof<'T>) x y
But then what's the point of resolving on the output parameter?
Well in this case makes no sense, but for type functions it would.
Upvotes: 3