6

I'm trying to pick up the concept of GADTs with Haskell and was trying to following Peano Number scenario,

{-# 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

However, I find when I compile this with the -fwarn-incomplete-patterns flag (GHC-7.6.3) it gives me the following warning even though all the possible patterns have been catered for:

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

however when i include a match for either of those patterns like so:

testFunc TypeCons1 (TypeCons2 {})       = 3

The compiler (correctly so) gives me the following error:

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

Is there any way to write this function or data type without adding a testFunc _ _ = undefined line which essentially makes the warn-incomplete-patterns flag useless for this function and clutters up my code with redundant ugly junk?

unfoldr
  • 141
  • 3

1 Answers1

0

One way would be to use type class:

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
Ankur
  • 33,367
  • 2
  • 46
  • 72