When I try to pattern-match a GADT in an proc
syntax (with Netwire and Vinyl):
sceneRoot = proc inputs -> do
let (Identity camera :& Identity children) = inputs
returnA -< (<*>) (map (rGet draw) children) . pure
I get the (rather odd) compiler error, from ghc-7.6.3
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: Identity cam :& Identity childs
I get a similar error when I put the pattern in the proc (...)
pattern. Why is this? Is it unsound, or just unimplemented?
Consider the GADT
and the execution of the code
In a dictionary-based Haskell implementation, one would expect that the value
s
is carrying a class dictionary, and that thecase
extracts theshow
function from said dictionary so thatshow x
can be performed.If we execute
we get an exception. Operationally, this is expected, because we can not access the dictionary. More in general,
case (undefined :: T) of K -> ...
is going to produce an error because it forces the evaluation ofundefined
(provided thatT
is not anewtype
).Consider now the code (let's pretend that this compiles)
and the execution of
What should this do? One might argue that it should generate the same exception as with
foo
. If this were the case, referential transparency would imply thatfails as well with the same exception. This would mean that the
let
is evaluating theundefined
expression, very unlike e.g.which evaluates to
5
.Indeed, the patterns in a
let
are lazy: they do not force the evaluation of the expression, unlikecase
. This is why e.g.successfully evaluates to
5
.One might want to make
let S = e in e'
evaluatee
if ashow
is needed ine'
, but it feels rather weird. Also, when evaluatinglet S = e1 ; S = e2 in show ...
it would be unclear whether to evaluatee1
,e2
, or both.GHC at the moment chooses to forbid all these cases with a simple rule: no lazy patterns when eliminating a GADT.