在限制带有类型族的GADT时,摆脱“非详尽的模式匹配”警告

时间:2012-09-15 16:02:38

标签: haskell pattern-matching warnings ghc type-families

鉴于以下计划:

{-# LANGUAGE DataKinds, GADTs #-}
{-# LANGUAGE TypeFamilies #-}

data Foo = A | B
type family IsA (foo :: Foo) :: Bool

type instance IsA A = True
type instance IsA B = False

data Bar (foo :: Foo) where
    BarA :: (IsA foo ~ True) => Int -> Bar foo
    BarB :: (IsA foo ~ False) => String -> Bar foo

f :: Bar A -> Int
f bar = case bar of
    BarA x -> x

当使用-fwarn-incomplete-patterns来定义上面定义的总函数f时,我从GHC 7.4.2收到此警告:

Warning: Pattern match(es) are non-exhaustive
         In a case alternative: Patterns not matched: BarB _

当然,即使尝试为BarB添加匹配也没有意义:

Couldn't match type `'False' with `'True'
Inaccessible code in
  a pattern with constructor
    BarB :: forall (foo :: Foo). IsA foo ~ 'False => String -> Bar foo,
  in a case alternative
In the pattern: BarB _
In a case alternative: BarB _ -> undefined
In the expression:
  case bar of {
    BarA x -> x
    BarB _ -> undefined }

有没有办法说服GHC f总计?此外,这是GHC的一个错误,还是一个已知的限制;或者实际上有一个很好的理由说明为什么无法看到f中的模式匹配是否完整?

2 个答案:

答案 0 :(得分:9)

这很烦人,是的。 GHC假设类型族(和类)在各地的算法中都是开放的。但是,您正在编写一个由封闭类型参数化的类型系列。这种紧张解释了你和GHC之间的误解。我认为已经考虑过如何处理封闭式类和家庭,但这是一个棘手的领域。

与此同时,您可以避免类型系列的开放性来说服整体检查。

{-# LANGUAGE DataKinds, GADTs #-}
{-# LANGUAGE TypeFamilies #-}

data Foo = A | B

data Bar (foo :: Foo) where
    BarA :: Int    -> Bar A -- or BarA :: foo ~ A => Int    -> Bar foo
    BarB :: String -> Bar B -- or BarB :: foo ~ B => String -> Bar foo

f :: Bar A -> Int
f bar = case bar of
    BarA x -> x
-- or f (BarA x) = x

答案 1 :(得分:1)

您始终可以使用_将匹配模式作为案例的最后一个条件。

所以_ -> undefined代替BarB _ -> undefined

这将使其论证中的案例总数。

Neil Mitchell还有一个library,它会检查非穷举模式,以防止因不匹配模式而导致运行时失败。