2013-03-12 81 views
10

我试图围绕Haskell中的函数应用程序运算符($)进行打包。试图了解Haskell中的函数应用程序运算符

我通过实例工作了解您一个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

在GHCi提示符下尝试一些东西后,可以通过**'Prelude>:t it **来检查它的* type *。 “It”是一个特殊的词,指的是前一个结果,而':t'则要求查看一个类型。你可以看到你最后一个例子中的数字没有小数点。此外,在提示符处输入**':s + t' **后,GHCi将报告产生的每个结果的类型。 – 2013-03-13 09:06:04

回答

17

的类型使用幂运算符的是

(^) :: (Num a, Integral b) => a -> b -> a 

所以当你使用\x -> 2^x,你会得到一个Integral约束的3。但是sqrt施加了Floating约束。所以3的类型必须满足

3 :: (Integral t, Floating t) => t 

但没有实例都默认类型列表中,这是IntegerDouble之中,所以渎职失败,你留下了一个模糊的类型变量。

当你有\x -> x^2,也不仅是从第一功能Num约束,并从sqrtFloating,所以类型被默认为Double

你可以,如果你使用

(**) :: Floating a => a -> a -> a 

为您幂运算符,那么类型可以再次被默认为Double它的工作。

+3

然后他可以修复它,用(**)替换(^)。 – zurgl 2013-03-12 13:57:37

+0

感谢丹尼尔和Zurgl--这可以大大地澄清事情。来自Python我仍然围绕着严格类型检查的含义。 – 2013-03-12 14:01:42