【问题标题】:State Monad - While-loopsState Monad - While 循环
【发布时间】:2014-02-18 10:14:43
【问题描述】:

这个问题的灵感来自this question。 我理解这个例子(ListBuilder),但我无法为我的状态单子创建一个while 循环。我不清楚的是如何bindwhileloop 的主体,因为迭代一个接一个。

谢谢。

/////////////////////////////////////////////////////////////////////////////////////
// Definition of the state 
/////////////////////////////////////////////////////////////////////////////////////
type StateFunc<'State, 'T> = 'State -> 'T * 'State



/////////////////////////////////////////////////////////////////////////////////////
// Definition of the State monad 
/////////////////////////////////////////////////////////////////////////////////////
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')

    member b.Zero() = fun s -> (), s

    member b.Delay f = f

    member b.Run f = f () 

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

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

    // (unit -> bool) * M<'T> -> M<'T>
    member b.While (cond, body: StateFunc<'State, _>): StateFunc<'State, _> = 
        (fun s ->
            if cond () then  
                let bind = 
                    let _, s' = body s
                    fun s' -> body s'    
                b.While (cond, bind) // This is wrong
            else
                body s)

【问题讨论】:

标签: f# monads state-monad guard-clause


【解决方案1】:

如果您查看 ExtCore 中的不同计算构建器,有一件有趣的事情需要注意 - 对于任何 monad,While(以及 For)成员的实现通常是相同的。

这是因为您始终可以用BindZeroWhile 的递归使用来表达操作。因此,如果您正在使用 monad,您将始终定义类似这样的内容(只需将 M&lt;_&gt; 替换为您的 monad):

// (unit -> bool) * M<'T> -> M<'T>
member this.While (guard, body : M<_>) : M<_> =
    if guard () then
        this.Bind (body, (fun () -> this.While (guard, body)))
    else
        this.Zero ()

这对于 所有 计算来说是不正确的 - 如果计算在某些方面更有趣,那么它可能需要 While 的不同实现,但以上是合理的默认值。

除此之外 - 我认为在 F# 中定义自定义计算表达式的需求应该非常少 - 惯用的 F# 代码几乎不像例如Haskell 和大多数时候,您应该对标准库的内容(或 ExtCore 定义的内容,如果您正在做更高级的事情)感到满意。也许您需要自定义计算,但请记住,这可能会分散您的注意力,导致您误入歧途...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-19
    • 1970-01-01
    • 2013-05-16
    • 2014-09-11
    • 2016-04-24
    • 1970-01-01
    • 1970-01-01
    • 2011-05-07
    相关资源
    最近更新 更多