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

如何不使用flipType定义《Haskell从First Principles》第18章习题5的meh函数?

问题与解答:不依赖flipType逻辑实现meh函数

我懂你现在的困扰——之前写的meh用了自己实现的concatMonads,但这个函数的功能和后面要做的flipType几乎一模一样,完全绕开了练习想要的递进逻辑。其实我们可以直接从Monad的核心操作出发,用递归遍历列表的方式来实现meh,完全不用提前拼接一堆m b值。

正确的实现思路

不用先把整个列表转成[m b]再处理,而是直接逐个处理列表元素:

  • 遇到空列表,直接返回一个包含空列表的Monad值(pure [])
  • 遇到非空列表,先把第一个元素通过transform转成m b,然后用Monad的绑定操作(>>=),把这个值和剩余列表的meh结果结合,把当前的b放到结果列表的最前面。

代码实现(基础版)

meh :: Monad m => [a] -> (a -> m b) -> m [b]
meh [] _ = pure []
meh (x:xs) transform = 
  transform x >>= \currentB -> 
    meh xs transform >>= \remainingBs -> 
      pure (currentB : remainingBs)

用do notation简化(更易读)

如果觉得嵌套的>>=看着头疼,用Haskell的do语法糖可以让代码更清晰:

meh :: Monad m => [a] -> (a -> m b) -> m [b]
meh [] _ = pure []
meh (x:xs) transform = do
  currentB <- transform x
  remainingBs <- meh xs transform
  pure (currentB : remainingBs)

为什么这样符合要求?

这个实现完全没有先把列表转换成[m b]再拼接的步骤,而是从头开始用Monad的绑定操作逐步构建最终的m [b]值,完美避开了类似flipType的逻辑。这样后续就可以按照题目要求,轻松用meh实现flipType:

flipType :: Monad m => [m b] -> m [b]
flipType l = meh l id

这样整个练习的递进逻辑就通顺了——先实现处理列表+转换函数的meh,再复用它实现把[m b]转成m [b]的flipType。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:00:48