有人可以解释一下这段代码在 F# 中的工作原理吗:
https://github.com/fsprojects/FSharpPlus/blob/master/src/FSharpPlus/Control/Functor.fs#L99-99
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>``>)
Run Code Online (Sandbox Code Playgroud)
具体来说call,该函数使用了我不理解的语法
例如
(^M or ^I or ^R)意思?... -> 'a当它似乎返回一个元组时,它如何具有类型签名?这种巫毒语法称为“静态解析类型参数”,简称 SRTP。
普通类型参数用勾号表示,例如'a。.NET 运行时本身支持这些类型参数,因此具有此类类型参数的类型和函数会直接编译为 IL 中的类和方法。
SRTP 用扬抑符表示,例如^M,并且不受.NET 运行时支持,因此无法编译为 IL,因此必须在编译时“展开”。这意味着对于参数化函数的每个使用位置,编译器必须确定 SRTP 应该是什么具体类型,并在调用位置插入函数的整个主体,也称为“内联”。这就是inline关键字的用途。
SRTP 的要点是表达一个约束,即“具有带有此签名的方法或属性的任何类型”。在您的特定示例中,这用这一行表示:
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)
Run Code Online (Sandbox Code Playgroud)
该行的意思是:
call,^M分别具有、^I和类型的三个元组参数^R,Map,(^I * ^R) * ^M,((source, mapping), mthd)作为参数传递。至于为什么它返回一个元组 - 它没有。最后一行的元组不是从Invoke函数返回,而是作为参数传递给call函数。call这是从 返回的结果Invoke。