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

Maybe类型中fmap双参函数传入Nothing为何未返回Nothing反而报错?

为什么fmap (++) Nothing报错而不是返回Nothing?

这个问题其实是个典型的「看起来结果不对,实则是类型打印卡壳」的小坑,我来给你拆解得明明白白:

核心真相:你其实已经得到了Nothing,只是它没法被打印出来

先回忆Functor的fmap类型签名:

fmap :: (a -> b) -> f a -> f b

咱们一步步拆解类型推导:

  1. (++)的类型是[x] -> [x] -> [x],可以把它看成接受一个列表,返回另一个函数——也就是(++) :: [x] -> ([x] -> [x]),这里的a就是[x],b就是([x] -> [x])。
  2. Nothing属于Maybe [x](因为fmap要求f a里的a要和前面的a匹配,也就是[x])。
  3. 所以fmap (++) Nothing的结果必然是Nothing :: Maybe ([x] -> [x])——没错,它就是你预期的Nothing!

那为什么会报错?因为GHCi默认会尝试打印你执行的表达式结果,而([x] -> [x])是个函数类型,Haskell的标准库并没有给函数类型实现Show实例(毕竟函数没法直接转换成可读的字符串),所以GHCi没法把这个Nothing打印出来,才抛出了那个关于No instance for (Show ([a0] -> [a0]))的错误。

对比fmap (+1) Nothing能正常打印的原因

(+1)的类型是Num a => a -> a,这里的b是数值类型(比如Int、Integer),这些类型都有标准的Show实例,所以fmap (+1) Nothing的结果Nothing :: Maybe Int可以被正常打印出来。

验证一下这个结论

你可以在GHCi里试试这两个操作:

  • 先绑定变量不打印:let res = fmap (++) Nothing,这时候不会报错,因为只是定义变量,不需要打印结果。
  • 查看结果的类型::t res,会得到res :: Maybe ([a] -> [a]),这直接证明结果确实是Nothing,只是类型里包含函数没法打印。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:53:27