Haskell部分应用程序似乎不适用于。为什么?

时间:2014-04-08 16:30:42

标签: 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的类型与比较的类型不同?

1 个答案:

答案 0 :(得分:5)

这是因为可怕的单态限制。 GHCi使用Monomorphism限制来猜测交互模式中定义的函数或值的最简单类型。这通常非常有用,但通常它是愚蠢的,并选择(),你真正想要一个类型类限制类型,如Ord a => a。只需为您的oc功能提供类型签名,您就可以了:

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

如果你喜欢:set -XNoMonomorphismRestriction(感谢@Xeo),你可以关闭Monomorphism限制,但我建议不要这样做。将您的函数放在一个文件中并将它们加载到GHCi中,或者以交互模式添加类型签名。


http://www.haskell.org/haskellwiki/Monomorphism_restriction上的wiki文章更详细地解释了这个问题。