Haskell,GADTs和-fwarn-incomplete-patterns

unf*_*ldr 6 haskell gadt

我正试图用Haskell来获取GADT的概念,并试图遵循Peano Number的情况,

{-# LANGUAGE GADTs, KindSignatures, DataKinds #-}
module Data.GADTTest where

data Height = Zero | Inc Height deriving (Show, Eq)

data TestGADT :: Height -> * where
    TypeCons1 :: TestGADT Zero
    TypeCons2 :: Int -> TestGADT h -> TestGADT (Inc h)

testFunc :: TestGADT h -> TestGADT h -> Int
testFunc TypeCons1 TypeCons1            = 1
testFunc (TypeCons2 {}) (TypeCons2 {})  = 2
Run Code Online (Sandbox Code Playgroud)

但是,我发现当我使用-fwarn-incomplete-patterns标志(GHC-7.6.3)编译它时,它给了我以下警告,即使所有可能的模式都已满足:

Pattern match(es) are non-exhaustive
    In an equation for `testFunc':
        Patterns not matched:
            TypeCons1 (TypeCons2 _ _)
            (TypeCons2 _ _) TypeCons1
Run Code Online (Sandbox Code Playgroud)

但是,当我为这些模式中的任何一个包含匹配时,如下所示:

testFunc TypeCons1 (TypeCons2 {})       = 3
Run Code Online (Sandbox Code Playgroud)

编译器(正确如此)给出了以下错误:

Couldn't match type 'Zero with 'Inc h1
Inaccessible code in
  a pattern with constructor
    TypeCons2 :: forall (h :: Height).
                 Int -> TestGADT h -> TestGADT ('Inc h),
  in an equation for `testFunc'
In the pattern: TypeCons2 {}
In an equation for `testFunc':
    testFunc TypeCons1 (TypeCons2 {}) = 3
Run Code Online (Sandbox Code Playgroud)

有没有办法编写这个函数或数据类型而不添加testFunc _ _ = undefined一行本质上使该warn-incomplete-patterns标志对此函数无用并使我的代码与冗余的丑陋垃圾混乱?

Ank*_*kur 0

一种方法是使用类型类:

class TestFunc a where
  testFunc :: a -> a -> Int

instance TestFunc (TestGADT Zero) where
  testFunc TypeCons1 TypeCons1 = 1
instance TestFunc (TestGADT (Inc h)) where
  testFunc (TypeCons2 _ _) (TypeCons2 _ _) = 2
Run Code Online (Sandbox Code Playgroud)