作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
有人可以解释一下这段代码在 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>``>)
特别是call
函数,它使用了我不理解的语法
例如
(^M 或 ^I 或 ^R)
是什么意思?... -> 'a
?最佳答案
这个巫术语法被称为 "Statically Resolved Type Parameters" ,或简称 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)
该行的含义是:
call
的函数,^M
、^I
和 ^R
的三个元组参数,Map
的静态方法,(^I * ^R) * ^M
,((source, mapping), mthd)
。至于为什么它返回一个元组 - 它没有。最后一行的元组不是从 Invoke
函数返回,而是作为参数传递给 call
函数。它是从 Invoke
返回的 call
的结果。
关于f# - 尝试了解仿函数在 FSharpPlus 中是如何实现的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72084228/
我是一名优秀的程序员,十分优秀!