mentics
mentics

Reputation: 6999

How do I specify type parameter in pattern matching for phantom type

Let's say I have this:

data PT1
data PT2
data DT1 a = DT1 { field :: Int }

newtype DT2 a = DT2 (DT1 a)

f :: Int -> DT2 a -> Int
f x (DT2 (DT1 PT1 field)) = 5 -- How do I specify the type param?
f x (DT2 (DT1 PT2 field)) = 7 -- How do I specify the type param?

The question is there in comments. The above doesn't compile. I want to pattern match differently based on the type parameter. How do I do so?

Upvotes: 2

Views: 326

Answers (2)

Antoine Latter
Antoine Latter

Reputation: 1555

If you want to have a pattern match provide evidence for a type parameter, you can use GADTs:

{-# LANGUAGE GADTs #-}

data PT1
data PT2

data Tag a where
    PT1 :: Tag PT1
    PT2 :: Tag PT2

data DT1 a = DT1 { tag :: Tag a, field :: Int }

newtype DT2 a = DT2 (DT1 a)

f :: Int -> DT2 a -> Int
f x (DT2 (DT1 PT1 field)) = 5
f x (DT2 (DT1 PT2 field)) = 7

But now the type is no longer a phantom type - you're carrying around a run-time tag.

I'm not sure what advantage this has over what @sepp2k suggested, or even if this would be useful. It just gives you what you asked for with minal modification to your example code :-)

Upvotes: 0

sepp2k
sepp2k

Reputation: 370377

You can't pattern match on the type. What you can do is use a typeclass like this:

class Effable t where
  f :: Int -> t -> Int

instance Effable (DT2 PT1) where
  f x (DT2 _) = 5

instance Effable (DT2 PT2) where
  f x (DT2 _) = 7

Upvotes: 3

Related Questions