【问题标题】:Computational Expression with Generics泛型计算表达式
【发布时间】:2013-11-25 13:40:35
【问题描述】:

我正在努力解决这个通用表达式:

type World<'a, 'b, 'c> = World of 'a * 'b * 'c
type StateFunc<'State, 'T> = 'State -> 'T * 'State


type StateMonadBuilder<'State>() =

    // M<'T> -> M<'T>
    member b.ReturnFrom a : StateFunc<'State, 'T> = a

    // 'T -> M<'T>
    member b.Return a : StateFunc<'State, 'T> = ( fun s ->  a, s)

    // M<'T> * ('T -> M<'U>) -> M<'U>
    member b.Bind(p : StateFunc<_, 'T>, rest : 'T -> StateFunc<_,_>) : StateFunc<'State, 'U>  = 
        (fun s ->
            let a, s' = p s
            rest a s')

    // Getter for the whole state, this type signature is because it passes along the state & returns the state
    member b.get : StateFunc<'State, _> = (fun s -> s, s)

    // Setter for the state
    member b.put (s:'State) : StateFunc<'State, _> = (fun _ -> (), s) 


let state = StateMonadBuilder<World<'a, 'b, 'c>> ()


let set1 a = state {
    let! World(_, b, c) = state.get
    do! state.put(World(a, b, c)) }


let set2 b = state {
    let! World(a, _, c) = state.get
    do! state.put(World(a, b, c))}


let testfun<'a, 'b> (one:'a) (two:'b) : StateFunc<World<'a, 'b, _>, _> = state {
    let! World(a,b,c) = state.get
    do printfn "%A" a
    do printfn "%A" b
    do printfn "%A" c
    do printfn "%A" "---------------------------"
    do! set1 one
    do! set2 two
    let! World(a,b,c) = state.get
    do printfn "%A" a
    do printfn "%A" b
    do printfn "%A" c
    do! state.put(World(a, b, c)) }


let appliedTest = testfun<int,int> 10 20
let result = appliedTest (World<int, int, int>(10, 20, 30))

目标是拥有一个继承World 的通用状态单子,一个三元组。 编译器报错testfun&lt;'a, 'b&gt; (one:'a) (two:'b)

错误 FS0670:此代码不够通用。类型变量 'a 无法泛化,因为它会超出其范围。

此外,World&lt;int, int, int&gt;(10, 20, 30) 声称类型参数是出乎意料的,这让我很惊讶。

我想问题实际上出在let state = StateMonadBuilder&lt;World&lt;'a, 'b, 'c&gt;&gt; (),换句话说,我不应该用泛型初始化状态构建器。

谢谢!

编辑 我认为我正在尝试做的事情是由于缺乏更高的种类而被阻止:http://cs.hubfs.net/topic/None/59392

【问题讨论】:

    标签: generics f#


    【解决方案1】:

    问题不在于缺少更高的种类,而是value restriction:您不能将state 定义为StateMonadBuilder&lt;World&lt;'a,'b,'c'&gt;&gt; 类型的泛型值。由于state 是纯的,因此单行解决方法是将state 改为type function

    let state<'a,'b,'c> = StateMonadBuilder<World<'a, 'b, 'c>> ()
    

    关于World&lt;int,int,int&gt;(10,20,30) 的问题 - type World 可以接受泛型参数,但 union case 不能。由于类型完全由构造函数的参数决定,如果你删除参数,它会被推断出来,但如果你想确定,你也可以添加一个类型注释:(World(10,20,30) : World&lt;int,int,int&gt;)

    【讨论】:

    • 太棒了,我不知道这个let state&lt;'a, 'b, 'c&gt; = StateMonadBuilder&lt;World&lt;'a, 'b, 'c&gt;&gt; ()是可能的!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多