Created
August 13, 2012 20:32
-
-
Save jbpotonnier/3343902 to your computer and use it in GitHub Desktop.
I try to understand phantom types in Haskell. In main, try eur 12 <+> usd 23 and see the compilation error, saying that you cannot add euros and US dollars. Neat ;)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
data EUR | |
data USD | |
data Amount a = Amount Float deriving Show | |
eur :: Float -> Amount EUR | |
eur a = Amount a | |
usd :: Float -> Amount USD | |
usd a = Amount a | |
(<+>) :: Amount a -> Amount a -> Amount a | |
(Amount a) <+> (Amount b) = Amount (a + b) | |
main = do | |
print $ eur 12 <+> eur 23 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# LANGUAGE GeneralizedNewtypeDeriving #-} | |
newtype Feet = Feet Double deriving (Num, Show, Eq) | |
newtype Cm = Cm Double deriving (Num, Show, Eq) | |
main = | |
print $ Feet 12 + Feet 12 |
GeneralizedNewtypeDeriving is providing derivation for numeric behaviour (Num typeclass)
It is less verbose than phantom types, no need for "smart constructors" (eur and usd), and all numeric functions for free.
I guess GeneralizedNewtypeDeriving is one of the many reasons ghc is so big :P
Deriving Num means that an expression like 12 + Feet 34
is valid, because Feed is now like a Num. It may or may not be what you want, depending of your application. I think if you define some new types that must not mix, then you don't want to mix them with Num.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
duplication