Why it is not possible to pattern match existential types in let
/where
, while it is doable in all other places?
TL;DR I have a funny error during let
pattern matching of existential types:
error:
• My brain just exploded
I can't handle pattern bindings for existential or GADT data constructors.
Instead, use a case-expression, or do-notation, to unpack the constructor.
• In the pattern: MC q
In a pattern binding: MC q = x
In the expression: let MC q = x in bar q
Details: let us start with some simple code:
{-# LANGUAGE ExistentialQuantification #-}
class MyClass a where
foo :: a -> Int
instance MyClass Int where
foo = id
instance MyClass Char where
foo = const 4
data MC = forall a. MyClass a => MC a
bar :: MyClass a => a -> Int
bar = (+1) . foo
This function runs great:
baz :: MC -> Int
baz (MC q) = bar q
and this:
qux :: MC -> Int
qux x = case x of
MC q -> bar q
even this:
import Control.Monad.Identity
osе :: MC -> Int
ose x = runIdentity $ do MC q <- pure x
pure $ bar q
but these two fail:
rol :: MC -> Int
rol x = let MC q = x
in bar q
zed :: MC -> Int
zed x = bar q
where MC q = x