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

如何使用>>=重写《Write Yourself A Scheme》中的parseNumber函数

正确实现

直接对应do语法脱糖的>>=版本

do表达式本质是Monad操作的语法糖,你给出的do块脱糖后直接对应以下代码:

parseNumber :: Parser LispVal
parseNumber = many1 digit >>= \x -> return $ Number (read x)

脱糖规则说明:

  • 形如a <- action; rest的do语句,会被转换为action >>= \a -> rest
  • 你原来的do块只有两步,刚好对应一次>>=绑定操作:
    • 第一步many1 digit的类型是Parser String,作为>>=的左操作数
    • 右操作数是接收String类型参数x的lambda,内部把x转成Integer再包成Number构造器,最后用return抬到Parser Monad中,类型刚好匹配Parser LispVal

简化版本

利用Monad和Functor的性质,还可以进一步简化为更简洁的写法,效果完全等价:

-- <$>是fmap的中缀写法
parseNumber :: Parser LispVal
parseNumber = Number . read <$> many1 digit

原理是m >>= return . f等价于fmap f m,这里f就是Number . read,可以省略显式的lambda和return操作。

常见类型错误原因

你之前遇到类型不匹配,大概率是以下两种情况:

  • 忘记在lambda最后加return:如果直接写many1 digit >>= \x -> Number (read x),右操作数返回的是LispVal类型,不是Parser LispVal,就会类型报错
  • 搞错了>>=两侧的类型匹配关系:>>=左操作数是Parser a,右操作数必须是a -> Parser b,两边的a类型要对应上

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 14:51:03