.net - 了解 F# 静态成员约束(构造小于通用警告)

标签 .net static f# inline type-constraints

另一位成员建议的这段代码允许 fmap 一般与 Option 和 Choice 一起工作,可以完美编译和工作,但是有一个警告我正在努力理解和修复。最后一行,在“Functor”下:

此构造导致代码不够通用。类型变量 'b 已被限制为 Functor。

type Functor = Functor
    with 
    static member FMap (Functor, mapper : 'T -> 'U, opt : Option<'T>) : Option<'U> =
        Option.map mapper opt
    static member FMap (Functor, mapper : 'T -> 'U, ch : Choice<'T, _>) : Choice<'U, _> =
        match ch with
        |Choice1Of2 v -> Choice1Of2 (mapper v)
        |Choice2Of2 v -> Choice2Of2 v

let inline fmap (f : ^c -> ^d ) (x : ^a) =
    ((^b or ^a) : (static member FMap : ^b * ( ^c -> ^d ) * ^a -> ^e ) (Functor, f, x))

这是有道理的,因为 ^b 应该始终是仿函数。

我想重新编写代码来解决此警告,但没有成功。

为此,为什么我需要 (^b 或 ^a) 而不仅仅是 ^a,因为 ^b 始终是一个仿函数。我无法获得没有(^b 或 ^a)语法的编译版本。

此外,为什么有必要通过 Functor union 案例呢?这又是我无法理解和解决的问题。

欣赏任何清晰度。

最佳答案

您只需添加 #nowarn "0064" 或添加如下内部调用函数即可解决该警告:

let inline fmap (f :'c->'d) (x : 'a) : 'e = 
    let inline call (mthd : ^B, x : ^A) =
        ((^B or ^A) : (static member FMap: _ * (^c -> ^d ) * ^A -> ^e) (mthd, f, x))
    call (Unchecked.defaultof<Functor>, x)

它添加了额外的类型变量,这些变量直到调用时才被解决,这样对于类型推断来说并不明显,^B 是 ^a,^A 是 ^a,^B 是 Functor。

您需要 ^B 或 ^A 因为它需要在类型 Functor 中查找静态方法(对于预先存在的类型,如 Option 和 Choice),而且还需要查找由以下表示的 future 类型定义^A,这允许您稍后在代码中添加如下内容:

type MyType<'a> = MyType of 'a with
    static member FMap (Functor, mapper, MyType a) = MyType (mapper a)

并且仍然可以使用:

> fmap string (MyType 4) ;;
val it : MyType<string> = MyType "4"

最后值得一提的是,这项技术是由一个实验项目开创和完善的(通过观察并尝试模仿 + 运算符的约束),该项目现在是 F#+ 通用模块的一部分,所以你可以找到更多 complex examples there 包括“默认实现”。

关于.net - 了解 F# 静态成员约束(构造小于通用警告),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46264035/

相关文章:

c# - 如何通过编码将复选框添加到datagridview

c# - 除了使用 P/Invoke 之外,如何在 hBitmap 上调用 DeleteObject()?

java - 是否可以使用 Gson 实例作为模型 bean 中的静态字段(重用)?

java - 从静态调用非静态方法(在不同的类中)

c++ - 静态类或实例指针

.net - 带超时的 F# 异步工作流

.net - 如何将关联数组参数从 javascript 传递到 ActiveX 对象?

algorithm - F#写红黑树的难点

c# - 在 F# 中使用程序集属性

c# - 有没有办法在 C# 中使用访问器的参数