国家 Monad - HASKELL

State Monad - HASKELL

提问人:Rifat Ahmed 提问时间:11/13/2023 最后编辑:Rifat Ahmed 更新时间:11/14/2023 访问量:94

问:

instance Monad ST where
   --return :: a -> ST a
   return x = S (\s -> (x,s))

   --(>>=) :: ST a -> (a -> ST b) -> ST b
   st >>= f = S (\s -> let (x, s') = app st s
                            in app (f x) s')

type State = Int
newtype ST a = S (State -> (a, State))

data Tree a = Leaf a | Node (Tree a) (Tree a) deriving (Show)

app :: ST a -> State -> (a, State)
app (S st) s = st s

mlabel :: Tree a -> ST (Tree Int)
mlabel (Leaf _) = fresh >>= (\n -> return (Leaf n))
mlabel (Node l r) = mlabel l >>= (\l ->
                    mlabel r >>= (\r ->
                    return (Node l r)))
fresh :: ST Int
fresh = S (\n -> (n , n +1))

嗨,所以这是我的代码,我想确保我对 mlabel 函数扩展的理解是正确的。而且我没有使用任何其他导入。

So suppose mlabel gets a input of Leaf 'a'

fresh >>== (\n -> return (Leaf n))
S (\n -> (n, n+1) >>== (\n -> return (Leaf n))
= S (\s -> let (x, s') = app (S (\n -> (n, n+1)) s
               (x, s') = (s, s+1)
               in app ((\n -> return (Leaf n) x) s'
                = app (S (\x -> (Leaf x, x+1)) s'
                = (\x -> (Leaf x, x+1) s'
                = (Leaf s+1, (s+1)+1)




Haskell -变形金刚 状态-Monad

评论

1赞 jpmarinier 11/13/2023
您可能希望包括 Tree 的定义,以及您正在使用的子句。import
1赞 Rifat Ahmed 11/14/2023
嗨,我添加了其他信息。@jpmarinier

答:

3赞 K. A. Buhr 11/14/2023 #1

您还没有包含此单子的 your 和 operations 的定义,但我假设您有类似的东西:>>=return

return x = S (\s -> (x, s))

a >>= f = S $ \s ->
  let (x, s') = app a s
  in app (f x) s'

如果是这样,那么您的扩展存在问题:

    app ((\n -> return (Leaf n) x) s'
=   app (S (\x -> (Leaf x, x+1)) s'

你在第一行缺少一个右括号,我认为你跳过了太多步骤,让自己转过身来。

无论如何,这应该看起来更像是这样:

    app ((\n -> return (Leaf n)) x) s'
=   app (return (Leaf x)) s'                -- apply lambda
=   app (S (\s -> (Leaf x, s))) s'          -- definition of `return`
=   (Leaf x, s')                            -- evaluate `app`

现在,当我们代入 和 from 的值时,我们得到:xs'let (x, s') = (s, s+1) in ...

=   (Leaf s, s+1)

而不是.(Leaf s+1, (s+1)+1)

重写整个语句可能比尝试单独重写 和 部分更安全,因此:let xxx in yyyxxxyyy

    S $ \s -> let (x, s') = app (S (\n -> (n, n+1))) s
              in app ((\n -> return (Leaf n)) x) s'
-- apply lambda
=   S $ \s -> let (x, s') = app (S (\n -> (n, n+1))) s
              in app (return (Leaf x)) s'
-- definition of `return`
=   S $ \s -> let (x, s') = app (S (\n -> (n, n+1))) s
              in app (S (\s -> (Leaf x, s))) s'
-- expand both `app` calls:
=   S $ \s -> let (x, s') = (s, s+1)
              in (Leaf x, s')
-- substitute `let` definitions:
=   S $ \s -> (Leaf s, s+1)

评论

0赞 Rifat Ahmed 11/14/2023
非常感谢,我真的被困住了。但是我有一个问题,难道不会首先评估第一个应用功能应用程序吗?那么返回的呢?
1赞 K. A. Buhr 11/14/2023
在Haskell中,函数的应用顺序并不重要(除了在一些“奇怪”的情况下),所以当你试图弄清楚一个表达式将如何计算时,你有相当大的自由来选择顺序,以及一次计算一个函数或一次计算多个函数在一个“步骤”中。您选择的任何顺序都应产生相同的最终答案。
0赞 Rifat Ahmed 11/14/2023
哇,太酷了。不知道。无论如何,谢谢你的帮助。