[Haskell-cafe] Re: distinguish functions from non-functions in a
class/instances
apfelmus
apfelmus at quantentunnel.de
Sat Dec 8 04:51:28 EST 2007
Luke Palmer wrote:
>
> Hmm, this still seems ill-defined to me.
>
> compose :: (Int -> Int -> Int) -> (Int -> Int) -> Int -> Int -> Int
>
> Is a valid expression given that definition (with a,b = Int and c = Int -> Int),
> but now the arity is 4.
That's correct, the arity of a function is not well-defined due to
polymorphism. The simplest example is probably
id :: a -> a -- "arity" 1
id = ($) :: (a -> b) -> (a -> b) -- "arity" 2
Therefore, the polymorphic expression
wrap id
is problematic. It roughly has the type
wrap id ~~ [String] -> a
But it's clearly ambiguous: do we have
wrap id (x:_) = read x
or
wrap id (f:x:_) = wrap ($) (f:x:_) = read f (read x)
or what? (assuming a read instance for function types)
GHCi gives it a type
> :type wrap id
wrap id :: (FunWrap (a -> a) y) => [String] -> y
but trying to use it like in
> let x = wrap id ["1"] :: Int
yields lots of type errors. We have to specialize the type of id
before supplying it to wrap . For example,
wrap (id :: Int -> Int)
works just fine.
I don't like this behavior of wrap since it violates the nice property
of polymorphic expressions that it's unimportant when a type variable is
instantiated, like in
map ((+1) :: Int -> Int) [1..5]
= map (+1) ([1..5] :: [Int])
= (map (+1) [1..5]) :: [Int]
Regards,
apfelmus
More information about the Haskell-Cafe
mailing list