Skip to content

Instantly share code, notes, and snippets.

@mathiasverraes
Last active June 21, 2016 21:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mathiasverraes/d65640372ac60c252b7aa05b2e49d9a9 to your computer and use it in GitHub Desktop.
Save mathiasverraes/d65640372ac60c252b7aa05b2e49d9a9 to your computer and use it in GitHub Desktop.
fooling around with haskell types and money
{-# LANGUAGE ExistentialQuantification #-}
module Money where
data Money a = Currency a => Money {currency :: a, amount :: Float}
instance Show (Money a) where
show (Money c a) = show c ++ " " ++ show a
instance Eq (Money a) where
(Money cx x) == (Money cy y) = cx == cy && x == y
class (Eq a, Show a) => Currency a where symbol :: a
data EUR = EUR deriving (Show, Eq)
instance Currency EUR where symbol = EUR
data USD = USD deriving (Show, Eq)
instance Currency USD where symbol = USD
eur :: Float -> Money EUR
eur = Money EUR
usd :: Float -> Money USD
usd = Money USD
instance Currency a => Monoid (Money a) where
mappend = (+)
mempty = Money symbol 0
instance Currency a => Num (Money a) where
(Money c x) + (Money _ y) = Money c (x + y)
(Money c x) * (Money _ y) = Money c (x * y)
abs (Money c a) = Money c (abs a)
signum (Money c a) = Money c (signum a)
fromInteger x = Money symbol (fromInteger x)
negate (Money c a) = Money c (negate a)
@mathiasverraes
Copy link
Author

λ> eur 5 + eur 6
EUR 11.0
λ> eur 5 + usd 6

<interactive>:27:9:
    Couldn't match type ‘USD’ with ‘EUR’
    Expected type: Money EUR
      Actual type: Money USD
    In the second argument of ‘(+)’, namely ‘usd 6’
    In the expression: eur 5 + usd 6
λ> sum [eur 5, eur 6, eur 7]
EUR 18.0

@mathiasverraes
Copy link
Author

Most of the functions from the Num class don't make a lot of sense, but you need them to be able to do (+)

@marijn
Copy link

marijn commented Jun 21, 2016

You need to explain this to me in person. I understand exactly nothing but I'm confident it's pretty clever 😉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment