【问题标题】:haskell State Monad put expressed using modifyhaskell State Monad put 使用 modify 表示
【发布时间】:2014-10-14 21:14:38
【问题描述】:

我需要使用 modify 函数来表达 State Monadput,但是我得到一个“无法推断”我的以下代码出错:

class Monad m => MonadState m s | m -> s where
    get :: m s
    get = modify (\s -> s)

    put :: s -> m ()
    put = modify $ const ()

    modify :: (s -> s) -> m s
    modify f = undefined  --do { x <- get; put (f x) }

(*我还没有定义修改,因为我在它旁边的评论中的实现也返回了类似的错误,但是在预期的返回类型 m s 而不是实际的返回类型 m ( ))

我得到的确切错误是:

Could not deduce (MonadState m ()) arising from a use of 'modify'
from context (MonadState m s)
  bound by the class declaration for 'MonadState'
  at <..>
Possible fix: add an instance declaration for (MonadState m ())
In the expression: modify
In the expression: modify $ const ()
In an equation for 'put': put = modify const ()

但是我不确定这个错误试图告诉我什么以及我在这里做错了什么。如果有人可以帮助我,将不胜感激!

最好的问候, Skyfe。

【问题讨论】:

    标签: haskell state monads


    【解决方案1】:

    const () 所做的就是将当前状态从任何状态转换为 ()。由于您希望它适用于所有状态,因此这将不起作用,因为这意味着它将状态类型从 s 更改为 ()。它也不会完全按照您的意愿去做。您可以使用const 函数,但最好不要先编写它。我建议让它变得有意义并使用明确的 lambda:

    put :: s -> m ()
    put newState = modify (\currentState -> ???)
    

    附带说明,您评论的modify 实现将不起作用,您真的需要

    modify f = do
        x <- get
        let newX = f x
        put x
        return x
    

    但是,我建议将modify 排除在类定义之外,就像mtl 所做的那样,因为只实现getput 确实更可取。这有助于防止循环定义。

    【讨论】:

    • 感谢您的修改现在工作!至于 put 函数:我先尝试了类似的东西,比如:put = modify (\s -> ()),但后来我得到了返回类型应该是 m() 而实际上是 () 的错误。我认为 newstate 应该转换为 () 作为 put 的返回值,但是我不明白它如何返回 m () 值。
    • 为什么要将状态转换为()?状态不是在改变类型,而是在改变值。你有一个新的状态,你应该用它做什么? () 出现的唯一原因是单子动作的结果为()。你可以把它想象成put :: s -&gt; State s a -&gt; State s ()而不是put :: s -&gt; State s a -&gt; State () a,你把()放在你心智模型的错误位置。
    • 这里我试图说明 put 不是作为一个单子函数,而是更多地作为 State 值的“设置器”。 s -&gt; State s a -&gt; State () a 的类型签名不会在实际代码中使用,仅用于说明目的。
    • 啊,我明白了,我想我脑子里的(返回)类型和(要设置的)值搞砸了。所以我基本上需要设置新的状态并返回m()。所以我想我会这样做: put s = modify (\s0 -> s) 设置新状态,然后从那里转到 m () 返回值?
    • 我想我明白了: put s = modify (\s0 -> s) >>= (\s1 -> return ()) - 将它的状态值修改为新的,然后绑定位于状态 monad 中的真实值,用于将其转换为新的 MonadState 值 ()。不确定我这样做是否正确?
    猜你喜欢
    • 2013-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-27
    • 1970-01-01
    • 2012-10-08
    • 2012-06-30
    相关资源
    最近更新 更多