2013-03-12 78 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