Reputation: 1037
Partially applying on with a single other function seems to change the types involved.
Starting with on compare length "aaa" "bb" and peeling off items from the right, things start off predictable:
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
But with on compare I got a surprise:
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"
Why is the type of oc not the same as the type of on compare?
Upvotes: 1
Views: 179
Reputation: 54068
This is because of the dreaded Monomorphism restriction. GHCi uses the Monomorphism restriction to guess the simplest possible type for a function or value defined in interactive mode. This is usually very useful, but quite often it is dumb and picks ()
where you really want a typeclass restrained type, like Ord a => a
. Just provide your oc
function a type signature and you'll be fine:
let oc :: Ord b => (a -> b) -> a -> a -> Ordering; oc = on compare
You can turn off the Monomorphism restriction if you'd like with :set -XNoMonomorphismRestriction
(thanks @Xeo), but I would recommend against it. Either put your functions in a file and load them into GHCi, or add type signatures in interactive mode.
The wiki article at http://www.haskell.org/haskellwiki/Monomorphism_restriction explains this problem in more detail.
Upvotes: 4