2014-04-08 90 views
2

部分應用其他功能似乎會改變所涉及的類型。Haskell部分應用程序似乎不適用於。爲什麼?

上比較長「AAA」,「BB開始」,並從右側脫落的物品,事情開始預見:

Prelude Data.Function> :t on compare length "aaa" "bb" 
on compare length "aaa" "bb" :: Ordering 

Prelude Data.Function> on compare length "aaa" "bb" 
GT 


Prelude Data.Function> :t on compare length "aaa" 
on compare length "aaa" :: [Char] -> Ordering 

Prelude Data.Function> let ocla = on compare length "aaa" 

Prelude Data.Function> :t ocla 
ocla :: [Char] -> Ordering 

Prelude Data.Function> ocla "aa" 
GT 


Prelude Data.Function> :t on compare length 
on compare length :: [a] -> [a] -> Ordering 

Prelude Data.Function> let ocl = on compare length 

Prelude Data.Function> :t ocl 
ocl :: [a] -> [a] -> Ordering 

Prelude Data.Function> ocl "aaa" "aa" 
GT 

但與比較我得到了一個驚喜:

Prelude Data.Function> :t on compare 
on compare :: Ord b => (a -> b) -> a -> a -> Ordering 

Prelude Data.Function> let oc = on compare 

Prelude Data.Function> :t oc 
oc :: (a ->()) -> a -> a -> Ordering 

Prelude Data.Function> oc length "aaa" "aa" 

<interactive>:27:4: 
    Couldn't match type `Int' with `()' 
    Expected type: [Char] ->() 
     Actual type: [Char] -> Int 
    In the first argument of `oc', namely `length' 
    In the expression: oc length "aaa" "aa" 
    In an equation for `it': it = oc length "aaa" "aa" 

爲什麼oc的類型與比較的類型不一樣?

回答

5

這是因爲可怕的單形態限制。 GHCi使用單態限制來猜測交互模式中定義的函數或值的最簡單類型。這通常是非常有用的,但通常它是愚蠢的,並且選擇(),你真的想要一個類型限制類型,如Ord a => a。只需提供您的oc功能的類型簽名,你會被罰款:

let oc :: Ord b => (a -> b) -> a -> a -> Ordering; oc = on compare 

您可以關閉單態的限制,如果你想與:set -XNoMonomorphismRestriction(感謝@Xeo)喜歡,但我會建議反對。把你的函數放在一個文件中並加載到GHCi中,或者在交互模式下添加類型簽名。


該維基文章http://www.haskell.org/haskellwiki/Monomorphism_restriction更詳細地解釋了這個問題。

+2

或者用GHCI中的':set -XNoMonomorphismRestriction'去。 – Xeo

+6

準確地說,它是與「ExtendedDefaultRules」組合的單態限制。前者強制單形類型。後者導致GHCi選擇'()'而不是報告錯誤。 – kosmikus

+0

@kosmikus TIL。我一定會提到下次這個問題會彈出。 – bheklilr

相關問題