[Haskell-cafe] Phantoms
Jason Dagit
dagit at codersbase.com
Thu Aug 14 02:43:37 EDT 2008
On Wed, Aug 6, 2008 at 11:09 AM, Andrew Coppin
<andrewcoppin at btinternet.com>wrote:
> I just (re)discovered that I can do things like
>
> data Foo x = Foo Int Int
>
> Now "Foo Int" and "Foo Double" are, as far as the type checker cares, two
> completely different types, even though in fact they are the same. This is
> actually Quite Useful, in the particular case I'm working on.
Phantom types are indeed useful for many things, but a bit of cautionary
advice. If you start to depend on the phantoms for type safety AND you
export your data constructors then you run a serious risk of being type
unsafe. Bonus points if you can demonstrate an equivalent of unsafeCoerce#
this way.
Example:
fooCast :: Foo Int -> Foo Double
fooCast (Foo x) = Foo x
On noes! We just cast that Foo Int to a Foo Double without changing it! It
works because the value on the RHS is consider freshly constructed and other
than sharing x it is unrelated to the one on the LHS.
Note that by contrast this does not type check:
foo :: Foo Int -> Foo Double
foo f@(Foo x) = f
Or, for that matter, any other variant where you don't use the constructor
on the RHS.
One way to get around this is to create your own constructor functions:
mkFooInt :: Int -> Foo Int
mkFooInt = Foo
mkFooDouble :: Int -> Foo Double
mkFooDouble = Foo
Now export these instead of your data constructor. Similarly you'll
probably want ones to take the place of pattern matching. The most obvious
general purpose one being:
unFoo :: Foo a -> Int
unFoo (Foo a) = a
But, if you're really relying on that phantom as a "witness", then you
should probably define separate unFooInt :: Foo Int -> Int and unFooDouble :
Foo Double -> Int.
Here is the part where it gets really interesting. If you use GADTs, it
rolls some of the above into one nice declaration:
data Foo a where
FooInt :: Int -> Foo Int
FooDouble :: Int -> Foo Double
I'm not sure if the GADT way can lead to an unsafeCoerce# equivalents or
not. Maybe someone else can comment on that.
Jason
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20080813/aa330faf/attachment.htm
More information about the Haskell-Cafe
mailing list