You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell State Monad代码:验证mlabel函数展开逻辑正确性

基于State Monad的树标记代码推导验证

核心代码定义

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函数实现

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函数定义

fresh :: ST Int
fresh = S (\n -> (n , n +1))

输入为Leaf 'a'时的推导过程(原文翻译+修正)

当输入为Leaf 'a'时,mlabel等价于fresh >>= (\n -> return (Leaf n)),以下是展开推导:

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
               -- 计算app结果:app (S st) s = st s,因此x=s,s'=s+1
               (x, s') = (s, s+1)
           in app ((\n -> return (Leaf n)) x) s')
= app (return (Leaf s)) s'  -- 代入x=s
= app (S (\s'' -> (Leaf s, s''))) s'  -- 展开return的定义
= (Leaf s, s')  -- 计算app结果
= (Leaf s, s+1)  -- 代入s'=s+1

推导逻辑验证

原文推导存在几处错误:

  • 符号错误:将>>=误写为>>==;
  • return定义混淆:return (Leaf x)的正确展开是S (\s'' -> (Leaf x, s'')),原文错误地写成了S (\x -> (Leaf x, x+1)),混淆了值参数和状态参数;
  • 最终结果错误:正确结果应为(Leaf s, s+1),而非(Leaf s+1, (s+1)+1)。

正确的逻辑是:从初始状态s出发,fresh取出当前状态值s作为标记,同时将状态更新为s+1;随后return将标记为s的叶子节点包装,且不改变已更新的状态,最终得到带标记的叶子节点和自增后的状态。因此原文推导逻辑不正确,核心问题是对return的Monad实现理解偏差。

内容的提问来源于stack exchange,提问作者Rifat Ahmed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 09:15:05