gpt4 book ai didi

f# - 尝试了解仿函数在 FSharpPlus 中是如何实现的

转载 作者:行者123 更新时间:2023-12-02 18:12:31 25 4
gpt4 key购买 nike

有人可以解释一下这段代码在 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)

该行的含义是:

  1. 定义一个名为call的函数,
  2. 具有类型分别为 ^M^I^R 的三个元组参数,
  3. 并确保这些类型中至少有一个具有名为 Map 的静态方法,
  4. 该方法采用一个元组 (^I * ^R) * ^M,
  5. 我们调用该方法并将其作为参数传递 ((source, mapping), mthd)

至于为什么它返回一个元组 - 它没有。最后一行的元组不是从 Invoke 函数返回,而是作为参数传递给 call 函数。它是从 Invoke 返回的 call 的结果。

关于f# - 尝试了解仿函数在 FSharpPlus 中是如何实现的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72084228/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com