Haskell中fmap ($ 3) (4+)报错问题技术咨询
为啥
fmap ($ 3) (4+)会报错?我来给你掰扯清楚! 哈哈,这个问题我刚学Haskell的时候也踩过一模一样的坑!咱们先从你原本的正确例子说起,再一步步拆解错误的原因~
先回忆正确例子的逻辑
你提到的map ($ 3) [(4+), (10*), (^2), sqrt]之所以能正常运行,核心是map和($3)的配合:
($3)其实是个“函数应用小工具”,等价于\f -> f 3——它接收一个函数f,然后把3作为参数传给f。map会把这个小工具挨个套在列表里的每个函数上,比如(4+)就变成(4+) 3,最终得到[7,30,9,1.732...],完全符合预期。
你的错误写法问题出在哪?
你改成fmap ($ 3) (4+)后报错,根源是你误解了fmap对单个函数的作用,还搞混了操作对象的类型:
- 首先,
(4+)不是列表,它是一个单独的函数(类型是Num a => a -> a)。而Haskell里的函数本身属于Functor类型类,当你对函数使用fmap时,fmap f g等价于函数组合f . g——意思是把g的输出当成f的输入,而不是把f直接应用到g上。 - 咱们把
fmap ($3) (4+)展开看看:它等价于($3) . (4+),进一步展开就是\x -> ($3) ((4+) x),也就是\x -> (4 + x) 3。
这里的问题就炸锅了:4 + x本来应该是个数字,但现在你把它当成了一个函数,要给它传参数3!这就要求4 + x的类型是一个函数,也就是编译器提示的Num (a -> b)——数字类型的实例居然是函数?这显然不符合Haskell的默认规则,所以才会抛出那个让人摸不着头脑的错误。
你真正想要的写法应该是这样
如果你只是想把(4+)这个函数应用到3上,根本不需要fmap,直接写就行:
-- 写法1:用($3)直接调用函数 ($3) (4+) -- 写法2:更直观的函数应用顺序 (4+) $3 -- 写法3:最直白的写法 (4+) 3
这三种写法的结果都是7,完全不会报错。
最后总结一下
- 当处理函数列表时,用
map ($3):把($3)应用到列表里的每个函数,得到一系列结果。 - 当处理单个函数时,直接用函数应用:要么把函数放前面参数放后面,要么用
$调整优先级,不需要画蛇添足用fmap。
内容的提问来源于stack exchange,提问作者Šefčíková Jana
相关产品推荐
相关产品推荐

