[Haskell-cafe] Rank2Types and pattern matching
Dan Doel
dan.doel at gmail.com
Sat Jul 3 23:33:56 EDT 2010
On Saturday 03 July 2010 10:52:31 pm Felipe Lessa wrote:
> I understood your explanation. However, is this an implementation
> detail/bug or is it an intended feature?
Well, I wouldn't call it a bug. Perhaps it could be called a lack of a
feature, because one can imagine such pattern matches being desugared into
case statements where instantiation is allowed to happen....
But, the example here is very simple, and I can raise some issues that might
convince you that this isn't a simple issue in general, and the GHC devs are
somewhat justified in not bothering to sort it out, at your expense. :)
First, what if we write:
runSomeMonad m@(SomeMonad x) = ...
What type does m have? We need to instantiate the argument to do the match on
the right, so is m bound to the instantiated value, or the polymorphic value?
I guess this comes down to whether the above desugars to:
runSomeMonad m = case m of
SomeMonad x -> ...
or:
runSomeMonad v = case v of
m@(SomeMonad x) -> ...
Second, the original example is uniform regardless of how 's' is instantiated,
but that might not be true in general. If we use data families for instance:
data family T a :: *
data instance T Int = I1 Int | I2 Char
data instance T () = U1 Int | U2
data instance T Char = C1 | C2 Int
f :: (forall a. T a) -> Int
...
Now, how are we going to be allowed to match in this function?
f (I1 i) = ...
f (I2 c) = ...
This, so far, desugars fine into something like:
f t = case t :: T Int of
I1 i -> ...
I2 c -> ...
but adding a third case makes the situation trickier:
f (U1 i) = ...
because that'd require instantiating t to a different type. Of course, you
could still desugar that to:
f t = case t :: T Int of
I1 i -> ...
I2 c -> ...
_ -> case t :: T () of
U1 i -> ...
but that third case is dead code. Or, should we allow mixing and matching, and
instantiate separately even at the same type:
f (I1 i) = ...
f (C2 i) = ...
f (U1 i) = ...
f (I2 i) = ...
becomes:
f t = case t :: T Int of
I1 i -> ...
_ -> case t :: T Char of
C2 i -> ...
_ -> case t :: T () of
U1 i -> ...
_ -> case t :: T Int of
I2 i -> ...
although that could be consolidated a bit.
That's off the top of my head. There may be other issues. Treating values with
polymorphic type as if they were some particular instantiation isn't a simple
matter, though.
-- Dan
More information about the Haskell-Cafe
mailing list