haskell - GADT type argument not being used for typeclass resolution -
consider following code
data foo f foo :: foo int class dynfoo t dynfoo :: foo f -> foo t instance dynfoo int dynfoo foo = foo obsfoo :: (dynfoo t) => foo f -> foo t obsfoo = dynfoo usedynfoo :: foo f -> int usedynfoo (obsfoo -> foo) = 1
the pattern match in usedynfoo
should constrain use of obsfoo
have type foo f -> foo int
, should cause search instance of dynfoo int
. however, instead searches instance of dynfoo t
unknown t
, , naturally fails.
no instance (dynfoo t0) arising use of ‘obsfoo’ type variable ‘t0’ ambiguous
however, if change definition of usedynfoo
to
usedynfoo :: foo f -> int usedynfoo (obsfoo -> (foo :: foo int)) = 1
then works, though type signature redundant.
so, why happening, , how can use obsfoo
without having give type signature?
it's clearer if write out explicit case
(view patterns pretty obscuring wrt type-information flow):
usedynfoo :: foo f -> int usedynfoo foof = case obsfoo foof of foo -> 1
here, information f ~ int
accessible 1
. well, that's not need information: need @ obsfoo foof
. , information can't there: gadt pattern matches act complete “type information diode”, i.e. information outside can used within matching scope, no information inside can used without. (for reasons obviously, because information can confirmed @ runtime, when have gadt constructor take from.)
the more interesting question is, why work if add :: foo int
signature? well, in particular weirdness of view pattern. see, following not work:
usedynfoo :: foo f -> int usedynfoo foof = case obsfoo foof of (foo :: foo int) -> 1
this information, said yourself, redundant.
however turns out view pattern equivalent putting signature on other part of case:
usedynfoo :: foo f -> int usedynfoo foof = case obsfoo foof :: foo int of foo -> 1
and quite different pair of shoes, because foo int
not inside gadt pattern match.
i don't know why view pattern signatures desugar this, perhaps make pattern possible.
Comments
Post a Comment