简体   繁体   中英

Haskell partial application doesn't seem to work with on. Why?

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?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM