Reputation: 1216
Can someone explain how this code works in F#:
static member inline Invoke (mapping: 'T->'U) (source: '``Functor<'T>``) : '``Functor<'U>`` =
let inline call (mthd: ^M, source: ^I, _output: ^R) = ((^M or ^I or ^R) : (static member Map : (_*_)*_ -> _) (source, mapping), mthd)
call (Unchecked.defaultof<Map>, source, Unchecked.defaultof<'``Functor<'U>``>)
Specifically the call
function, which uses a syntax which I do not understand
e.g.
(^M or ^I or ^R)
mean?... -> 'a
when it seems to return a tuple?Upvotes: 2
Views: 243
Reputation: 80915
This voodoo syntax is called "Statically Resolved Type Parameters", or SRTPs for short.
Normal type parameters are denoted with a tick, like 'a
. These type parameters are natively supported by the .NET runtime, so types and functions with such type parameters are compiled directly to classes and methods in IL.
SRTPs are denoted with a circumflex, like ^M
, and are not supported by the .NET runtime, and therefore cannot be compiled to IL, and therefore have to be "unrolled" during compilation time. This means that for every use site of thus parametrized function, the compiler must determine what concrete types the SRTPs should be, and insert the whole body of the function at call site, also known as "inlining". This is what the inline
keyword is for.
The point of SRTPs is to express a constraint saying "any type that has a method or property with this signature". In your particular example, this is expressed on this line:
let inline call (mthd: ^M, source: ^I, _output: ^R) = ((^M or ^I or ^R) : (static member Map : (_*_)*_ -> _) (source, mapping), mthd)
^^^^ ^^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^
(1) \----------||-----------/ (3) (4) (5)
(2)
The line means:
call
,^M
, ^I
, and ^R
respectively,Map
,(^I * ^R) * ^M
,((source, mapping), mthd)
as parameter.As to why it returns a tuple - it doesn't. The tuple on the last line is not returned from the Invoke
function, but passed as parameter to the call
function. It's the result of call
that is returned from Invoke
.
Upvotes: 5