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

Haskell中liftM Just执行结果不符预期是否为Bug?

关于Haskell中liftM行为的疑问解答

这不是Haskell的Bug,核心是对liftM的作用逻辑理解出现了偏差。

先明确liftM的本质

liftM的默认实现是:

liftM f m = m >>= return . f

它的作用是映射Monad容器内部的"成功值":尝试从Monad值m a中取出内部的a类型值,对其应用函数f得到b,再用return把b重新包回Monad结构,最终得到m b。

为何(liftM Just) Nothing返回Nothing而非Just(Nothing)?

对于Maybe这个Monad实例来说,其>>=操作的定义是:

  • Just x >>= f = f x
  • Nothing >>= _ = Nothing

当你调用(liftM Just) Nothing时,m是Nothing,触发了上面第二条规则,直接返回Nothing——因为Nothing里没有可供提取的a类型值,根本不会执行return . Just这一步。此时返回的Nothing类型是Maybe (Maybe a),完全符合函数签名。

同理,(liftM Just) (Left 1)返回Left 1的原因

Either e作为Monad时,>>=的定义是:

  • Right x >>= f = f x
  • Left err >>= _ = Left err

Left 1里携带的是错误值,并非Monad的"成功值",所以>>=直接返回原Left 1,不会执行Just函数。返回值类型是Either Int (Maybe a),同样符合函数签名。

如何得到Just(Nothing)?

你想要的是把整个Maybe值(不管是Just x还是Nothing)作为参数传给Just,而非映射Maybe内部的值。此时不需要用liftM,直接调用Just函数即可:

Just Nothing  -- 结果为Just(Nothing) :: Maybe (Maybe a)
Just (Left 1) -- 结果为Just(Left 1) :: Maybe (Either Int a)

如果需要一个通用函数,能把任意Monad值m a包裹成Maybe (m a),直接用Just本身就可以,它的类型签名是b -> Maybe b,当b取m a时,正好满足需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 19:23:15