试图了解Haskell中的函数应用程序运算符

Pau*_* M. 10 haskell operators

我试图$在Haskell中围绕函数应用程序operator().

我正在研究Learn You a Haskell中的示例,我认为我理解了以下示例:

Prelude> map ($ 3) [(+4), (*10), (^2), sqrt]
[7.0,30.0,9.0,1.7320508075688772] 
Run Code Online (Sandbox Code Playgroud)

然后我尝试了以下变体,它也运行良好:

Prelude> map ($ 3) [(+4), (*10), (\x -> x^2), sqrt]
[7.0,30.0,9.0,1.7320508075688772]
Run Code Online (Sandbox Code Playgroud)

最后,我尝试按如下方式修改列表中的第三个函数,这会生成错误:

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> 
Run Code Online (Sandbox Code Playgroud)

似乎最终sqrt函数以某种方式开始与前一个列表元素相关联,因为以下变体可以正常工作:

Prelude> map ($ 3) [(+4), (*10), (\x -> 2^x)]
[7,30,8]
Run Code Online (Sandbox Code Playgroud)

有人可以告诉我这里发生了什么吗?

Dan*_*her 17

使用的取幂运算符的类型是

(^) :: (Num a, Integral b) => a -> b -> a
Run Code Online (Sandbox Code Playgroud)

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

3 :: (Integral t, Floating t) => t
Run Code Online (Sandbox Code Playgroud)

但是默认类型列表中没有两个实例,这是IntegerDouble,因此默认失败,并且你留下了一个模糊的类型变量.

当你有\x -> x^2,只有Num第一个函数和Floatingfrom 的约束sqrt,所以类型默认为Double.

如果使用,可以使它工作

(**) :: Floating a => a -> a -> a
Run Code Online (Sandbox Code Playgroud)

作为你的指数运算符,那么类型可以再次默认为Double.

  • 然后他可以修复它,用(**)代替(^). (3认同)