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

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to