[Haskell-cafe] Newbie question (again!) about phantom types

Arie Peterson ariep at xs4all.nl
Wed Aug 8 11:59:19 EDT 2007

> I’m having difficulty to understand what phantom types are good for. Is
> this just for improving runtime performance?

No. As the wiki says, you can use them to add static guarantees.

> I read the wiki, and it says "this is useful if you want to increase the
> type-safety of your code", but the code below does not give a compiler
> error
> for the function test1, I get a runtime error, just like test2.

It seems you're mixing up GADT's and phantom types.

> -- CODE --
> -- With phantom types
> data T1 a = TI1 Int | TS1 String deriving Show

Here, the 'a' is an extra type parameter, which has no manifestation on
the value level. Note the type of the constructors:

TI1 :: Int -> T1 a
TS1 :: String -> T1 a

In particular, the 'a' is not related to the 'Int' or 'String' arguments.

> foo1 :: T1 String -> T1 String -> T1 String
> foo1 (TS1 x) (TS1 y) = TS1 (x++y)
> test1 = foo1 (TI1 1) (TI1 2) -- Shouldn't this give a compiler error
> instead
> of a runtime error?

'TI1 1' has type 'T1 a', so this unifies with 'T1 String' (the type of the
argument of 'foo1'.

The type parameter 'a' can still be useful, but you have to use an
explicit type signature to constrain the type 'a':

ti1 :: Int -> T1 Int
ti1 x = TI1 x

Now, 'ti1' will create values with the restricted type 'T1 Int', that you
can't use as arguments for your 'foo1'.

GADTs are perhaps more useful for what you seem to want. Try something
like this:

data T1 :: * -> * where -- T1 has one type parameter
  TI1 :: Int -> T1 Int
  TS1 :: String -> T1 String

Now, the type systems guarantees that all values of the form 'TI1 x' have
type 'T1 Int'.



More information about the Haskell-Cafe mailing list