I have the following code
{-# LANGUAGE DataKinds, GADTs, TypeOperators #-}
data Vect v a where
Nil :: Vect '[] a
Vec :: a -> Vect v a -> Vect (() ': v) a
instance Eq a => Eq (Vect v a) where
(==) Nil Nil = True
(Vec e0 v0) == (Vec e1 v1) = e0 == e1 && v0 == v1
When compiling or interpreting with -Wall
the following warning is given:
Pattern match(es) are non-exhaustive
In an equation for `==':
Patterns not matched:
Nil (Vec _ _)
(Vec _ _) Nil
Normally this is to be expected. Normally, even if I can reason that my patterns will cover all possible cases, there is no way for the compiler to know that without running the code. However, the exhaustiveness of the provided patterns are enforced by the type checker, which runs at compile time. Adding the patterns suggested by GHC gives a compile time time error:
Couldn't match type '[] * with `(':) * () v1'
So my question is this: do GHC warnings just not play well with GHC extensions? Are they supposed to be aware of each other? Is this functionality (warnings taking into account extensions) slated for a future release, or is there some technical limitation to implementing this feature?
It seems that the solution is simple; the compiler can try adding the supposedly unmatched pattern to the function, and asking the type checker again if the suggested pattern is well typed. If it is, then it can indeed be reported to the user as a missing pattern.
(==) _ _ = False
? – NellanelldaVector '[] a
isNil
? What about undefined? – Nellanelldaundefined
have to do with exhaustivity checking?not :: Bool -> Bool; not False = True; not True = False
doesn't need an_
case, and neither should this. – Telicv
is[]
, then the only possible constructor isNil
; ifv
is_ : _
, then the only possible constructor isVec
. Since the two types match, their constructors must also match (and GHC "knows" that, which is why it gives an error when you try to match on two different constructors). – Telic==
isEq a => a -> a -> Bool
or instantiated withVect v a
,Vect v a -> Vect v a -> Bool
. The type ofNil
isVect '[] a
and the type ofVec undefined Nil
(for example) isVect (() ': '[]) a
. Those two values can't be arguments to the==
function because their types differ. – Handhold