了解f#静态成员约束(构建少于通用警告)



另一个成员建议的这件代码允许FMAP与选项和选择的编译和完美工作,但我努力理解和修补。最后一行,"函子"下:

此构造导致代码小于通用。类型变量'B已被约束到函子。

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 as ^b永远是函子。我一直无法获得没有( ^b或 ^a)语法的编译版本。

此外,为什么有必要通过Foundor Union Case通过。同样,我无法理解和工作的事情。

感谢任何清晰度。

您可以通过添加#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是函数。

您需要^B or ^A,因为它需要在类型函数中查找静态方法(对于诸如选项和选择(例如选项和选择),但对于由^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# 的通用模块的一部分,以便您可以找到更多的方法,以便您可以找到更多那里的复杂示例包括"默认实现"。

最新更新