我正试图在Haskell中绕过函数应用程序运算符($
)。
我正在研究Learn You a Haskell中的示例,我认为我理解了以下示例:
Prelude> map ($ 3) [(+4), (*10), (^2), sqrt]
[7.0,30.0,9.0,1.7320508075688772]
然后我尝试了以下变体,它也运行良好:
Prelude> map ($ 3) [(+4), (*10), (\x -> x^2), sqrt]
[7.0,30.0,9.0,1.7320508075688772]
最后,我尝试按如下方式修改列表中的第三个函数,这会产生错误:
Prelude> map ($ 3) [(+4), (*10), (\x -> 2^x), sqrt]
<interactive>:53:38:
Ambiguous type variable `b0' in the constraints:
(Floating b0)
arising from a use of `sqrt' at <interactive>:53:38-41
(Integral b0) arising from a use of `^' at <interactive>:53:33
(Num b0) arising from the literal `3' at <interactive>:53:8
Probable fix: add a type signature that fixes these type variable(s)
In the expression: sqrt
In the second argument of `map', namely
`[(+ 4), (* 10), (\ x -> 2 ^ x), sqrt]'
In the expression: map ($ 3) [(+ 4), (* 10), (\ x -> 2 ^ x), sqrt]
Prelude>
似乎最终的sqrt
函数以某种方式开始与前一个列表元素相关联,因为以下变体可以正常工作:
Prelude> map ($ 3) [(+4), (*10), (\x -> 2^x)]
[7,30,8]
有人可以告诉我这里发生了什么吗?
答案 0 :(得分:17)
使用的取幂运算符的类型是
(^) :: (Num a, Integral b) => a -> b -> a
因此,当您使用\x -> 2^x
时,您会Integral
获得3
约束。但是sqrt
强加了Floating
约束。所以3的类型必须满足
3 :: (Integral t, Floating t) => t
但默认类型列表中没有两个实例,即Integer
和Double
,因此默认值失败,并且您留下了一个模糊的类型变量。
当你有\x -> x^2
时,第一个函数只有Num
个约束,而Floating
只有sqrt
,所以类型默认为Double
}。
如果您使用
,则可以使其正常工作(**) :: Floating a => a -> a -> a
作为指数运算符,然后该类型可以再次默认为Double
。