Closed Ingo60 closed 11 years ago
This is due to REPL trying to assign the script to a variable to identify whether the script is an expression. The same code outside REPL in a normal Frege program also fails. For example, the following code fails with the same compilation error:
module HelloWorld where
bar :: (forall b.[b]->[b]) -> ([Int], [Bool]); bar f = (f [0x1,0x2], [true, false])
foo = bar
REPL runs the lexer phase with that assignment to see if the script is an expression. In this case it succeeds and then at the later point it fails to compile as in the above program. If the REPL can identify that as not an expression or if the above regular Frege program results in successful compilation, it will succeed. For example, In the following code in REPL, with the import in front, it is not identified as an expression so the assignment won't happen and it succeeds.
frege> import Data.List;bar :: (forall b.[b]->[b]) -> ([Int], [Bool]); bar f = (f [0x1,0x2], [true, false])
frege> bar id
([1, 2], [true, false])
I have found some bugs in the handling of higher rank typed code, see the latest Issues in frege. Maybe we can delay this one until they're fixed, as it is not that important.
We might also want to treat foo = bar
specially, because in the eta-expanded form this is indeed a type error when bar is higher rank and there is no annotation available for foo.
We might also want to treat
foo = bar
specially, because in the eta-expanded form this is indeed a type error
My type-fu is at very much beginner level. How is that a type error? If you can point me to some papers, that would also be great. By the way, the same (foo = bar
) works fine in Haskell.
I guess it is because they actually do treat it specially. (I'll ask this on SO next time.)
Without considering special cases, HM type inference cannot infer a higher rank type for anything. Hence, the type inferred for foo
will by necessity be not polymorphic enough.
The following also results in type error in Haskell (GHCi 7.4.2, with :set -XRankNTypes):
foo f = bar f
The point is that the argument f can not get the polymorphic type needed through type inference. So even in Haskell one would need a type signature for foo
to make it check.
I got it now, thanks! So now we need to figure out how to resolve this as a declaration instead of assigning to a variable which lexer and parser seem to agree and then getting treated as an expression that later on fails with typechecker.
I'll post a fix in a few minutes that enhances typechecking in the case where the left hand side is a single identifier and the right hand side is a partial application of a higher rank function up to, but excluding, the polymorphic function argument or just that function.
Hence if we have
bar :: Bool -> (forall.[a]->[a]) -> [b] -> [b]
the following is ok:
foo = bar -- foo :: Bool -> (forall.[a]->[a]) -> [b] -> [b]
baz = bar true -- baz :: (forall.[a]->[a]) -> [b] -> [b]
while this is wrong:
wrong f = bar true f
This is just like it works in GHC, according to my tests.
P.S. one can, of course, also pass the function argument, but it must not contain a lambda/case-bound name.
Hence:
good = baz true reverse
but, of course, good
is then not higher rank itself.
Take the following example, which serves to demonstrate higher rank functions:
This code checks just fine in the compiler. However, in the online REPL it gives nonsensical messages:
I also tried this with :{, :}, no difference. An interesting aspect is that the alternate definition does work: