Reputation: 2795
consider this code
open System.Runtime.CompilerServices
[<Extension>]
type Foo =
[<Extension>]
static member inline classID (any : ^T) : ^U =
(^T : (member classID : Unit -> ^U) any)
[<Extension>]
static member inline parent (any : ^T) : ^U =
(^T : (member parent : Unit -> ^U) any)
let inline foo (tx : _) =
tx.classID() + "!" + tx.parent().classID()
the first question is, what IS the signature of foo?
my intellisense says its
'a -> string (requires member classID and member parent and member classID)
which to be fair, is at best vague as there are 2 implicit type parameters involved here and it doesnt specify which type requires which member, but that may be a tooling issue.
Is it possible to write an explicit signature for this finction e.g. like this:
let bar : 'a -> string =
fun _ -> ""
i.e.
let [var] : [signature] =
fun [param] -> [result]
what would [signature] for foo?
(there will be an additional question about extracting this signature at run time, but I'll leave that as a seperate question)
Upvotes: 2
Views: 55
Reputation: 17038
Here's how I would write foo
with explicit type annotations:
let inline foo (tx : ^T
when ^T : (member classID : unit -> string)
and ^T : (member parent : unit -> ^U)
and ^U : (member classID : unit -> string)) : string =
tx.classID() + "!" + tx.parent().classID()
So, in theory, I suppose its signature is:
(^T
when ^T : (member classID : unit -> string)
and ^T : (member parent : unit -> ^U)
and ^U : (member classID : unit -> string)) -> string
It's not possible to write an explicit signature for bar
because bar
would have to be inline, and only functions can be inline, so bar
itself is impossible.
This is why I wrote "in theory" above. You can't use foo
's signature in actual F# code, so does it really have a signature at all? The root problem here is that statically resolved type parameters in F# are (IMHO) very flaky and poorly documented, so it's hard to know for sure if there is any truly correct answer to your question.
Upvotes: 2