2

So I'm playing around with the y-combinator and anonymous functions, and I ran into this weird error:

Couldn't match expected type `t0 -> t1 -> t2'
            with actual type `forall b. b -> [b] -> [b]'
The lambda expression `\ (n :: Int) newVal xs -> ...'
has three arguments,
but its type `Int -> forall b. b -> [b] -> [b]' has only one

(source code that creates the error, and version that I eventually got working)

If I modify the types slightly to avoid Rank N polymorphism (use forall b. Int -> b -> [b] -> [b]), the error is similar:

Couldn't match expected type `t0 -> t1 -> t2 -> t3'
            with actual type `forall b. Int -> b -> [b] -> [b]'
The lambda expression `\ (n :: Int) newVal xs -> ...'
has three arguments,
but its type `forall b. Int -> b -> [b] -> [b]' has none

Could someone explain to me why forall b. b -> [b] -> [b] has no arguments?

Community
  • 1
  • 1
rampion
  • 82,104
  • 41
  • 185
  • 301
  • 1
    What version of GHC are you using? This looks like a bug in GHC 7 that prevents unification of implicitly and explicitly quantified types. http://hackage.haskell.org/trac/ghc/ticket/4347 – Carl May 04 '11 at 17:27
  • @Carl: 7.0.3 - This looks like exactly the problem. Upgrade your comment to an answer and I'll accept it. – rampion May 04 '11 at 17:29
  • @Don Stewart: Making it type 1 by [changing the types to `forall b.Int -> b -> [b] -> [b]`](https://gist.github.com/955714) doesn't change the error much. – rampion May 04 '11 at 18:24

3 Answers3

2

Since you're using GHC 7, this appears to have the same root cause as the bug reported in http://hackage.haskell.org/trac/ghc/ticket/4347 . While that bug report talks about impredicative polymorphism, it seems like it's most likely in a unification problem in higher-rank polymorphism. In your case, it's being triggered by your placement of the forall, which makes the type syntactically rank-2.

Note that this isn't really a bug. The further clarification provided makes it clear this is intended behavior, in that polymorphic instantiations of types, including rank-N types and impredicative types, are not inferred. Careful addition of type signatures can make it work.

But since the type wasn't intended to be higher-rank, at all, in your case, it's best to just get rid of that.

Carl
  • 24,118
  • 4
  • 57
  • 79
0

Do you rather want

forall b. Int -> b -> [b] -> [b]

or really

Int -> forall b . b -> [b] -> [b]

I would read the latter: A function that takes an Int and returns SOMETHING OPAQUE THAT IS MOST LIKELY NOT WHAT YOU THINK IT IS.

Ingo
  • 34,949
  • 5
  • 49
  • 97
  • possibly, but my current goal is to apply and refine my current understanding of `forall`, and, in particular, to understand why it is that `forall b. b -> [b] -> [b]` takes no arguments, as the error indicates. – rampion May 04 '11 at 16:33
  • Actually, those two are not different at all, since the forall scopes over the remainder of the type, and the function is rank-1 either way. – Carl May 04 '11 at 17:31
  • 1
    I should clarify... The type is equivalent to a rank-1 type, even if it's written using rank-2 form. That's what I actually meant. – Carl May 04 '11 at 17:33
0

My guess was that you've written the wrong types down.

Removing the type annotations helps somewhat, leading to less confusing errors:

A.hs:7:76:
    Occurs check: cannot construct the infinite type: a0 = [a0]
    In the third argument of `replaceNth', namely `arg'
    In the expression: replaceNth m (replaceNth n v (arg !! m)) arg

so

 \m n v arg -> replaceNth m (replaceNth n v (arg !! m)) arg

has already got problems.


Rank N types and lexically scoped type variables

By using a forall not in an outermost position, you have stumbled into rank N types. The forall on your inner b says that it must be opaque, polymorphic, and unrelated to your other uses of the b type. This is likely not what you intended to do.

This is subtly distinct from lexically scoped type variables, which can also be introduced by a forall in the outermost position, as described here.

By removing the (I think) mistaken foralls in the non-outermost position, you will get much simpler type errors.

Don Stewart
  • 134,643
  • 35
  • 355
  • 461
  • if I replace the argument to `(\replaceNth -> ...)` with a value of type `Int -> forall b.b -> [b] -> [b]` (like `undefined` or `const . const id`), I don't get any such error, so I don't think that's the issue. – rampion May 04 '11 at 16:31
  • Note that that's a *rank N* type (the `forall` is on an inner position). Did you mean to introduce such a type there? It means your second `b` type will be distinct and unrelated to other `b`s in your type. Your question suggests you want scoped type variables, not rank N types. – Don Stewart May 04 '11 at 16:45
  • So, if I understand you correctly, `forall b.b -> [b] -> [b]` has 4 `b`s, which I'll call b0, b1, b2, and b3; and `b0 ~ b1` is a constraint, but `b0 ~ b2` and `b0 ~ b3` are not? – rampion May 04 '11 at 16:58
  • `forall b.b -> [b] -> [b]` has three arguments, all of which must be the same type (which can be any type). – Don Stewart May 04 '11 at 17:20