{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_GHC -Wno-orphans #-} -- | This module only exports orphan 'Ser.Serialise' instances. Import as: -- -- @ -- import "Money.Serialise" () -- @ module Money.Serialise () where import qualified Codec.Serialise as Ser import Control.Monad (when) import Data.Ratio ((%), numerator, denominator) import GHC.TypeLits (KnownSymbol) import qualified Money import qualified Money.Internal as MoneyI -------------------------------------------------------------------------------- -- | Compatible with 'Money.SomeDense'. instance (KnownSymbol currency) => Ser.Serialise (Money.Dense currency) where encode = Ser.encode . Money.toSomeDense decode = maybe (fail "Dense") pure =<< fmap Money.fromSomeDense Ser.decode -- | Compatible with 'Money.SomeDiscrete'. instance ( KnownSymbol currency, Money.GoodScale scale ) => Ser.Serialise (Money.Discrete' currency scale) where encode = Ser.encode . Money.toSomeDiscrete decode = maybe (fail "Discrete'") pure =<< fmap Money.fromSomeDiscrete Ser.decode -- | Compatible with 'Money.SomeExchangeRate'. instance ( KnownSymbol src, KnownSymbol dst ) => Ser.Serialise (Money.ExchangeRate src dst) where encode = Ser.encode . Money.toSomeExchangeRate decode = maybe (fail "ExchangeRate") pure =<< fmap Money.fromSomeExchangeRate Ser.decode instance Ser.Serialise Money.Scale where encode = \s -> let r = Money.scaleToRational s in Ser.encode (numerator r) <> Ser.encode (denominator r) decode = maybe (fail "Scale") pure =<< do n :: Integer <- Ser.decode d :: Integer <- Ser.decode when (d == 0) (fail "denominator is zero") pure (MoneyI.scaleFromRational (n % d)) -- | Compatible with 'Money.Dense'. instance Ser.Serialise Money.SomeDense where encode = \sd -> let r = Money.someDenseAmount sd in Ser.encode (MoneyI.someDenseCurrency' sd) <> Ser.encode (numerator r) <> Ser.encode (denominator r) decode = maybe (fail "SomeDense") pure =<< do c :: String <- Ser.decode n :: Integer <- Ser.decode d :: Integer <- Ser.decode when (d == 0) (fail "denominator is zero") pure (MoneyI.mkSomeDense' c (n % d)) -- | Compatible with 'Money.Discrete'. instance Ser.Serialise Money.SomeDiscrete where encode = \sd -> Ser.encode (MoneyI.someDiscreteCurrency' sd) <> Ser.encode (Money.someDiscreteScale sd) <> Ser.encode (Money.someDiscreteAmount sd) decode = do c :: String <- Ser.decode s :: Money.Scale <- Ser.decode a :: Integer <- Ser.decode pure (MoneyI.mkSomeDiscrete' c s a) -- | Compatible with 'Money.ExchangeRate'. instance Ser.Serialise Money.SomeExchangeRate where encode = \ser -> let r = Money.someExchangeRateRate ser in Ser.encode (MoneyI.someExchangeRateSrcCurrency' ser) <> Ser.encode (MoneyI.someExchangeRateDstCurrency' ser) <> Ser.encode (numerator r) <> Ser.encode (denominator r) decode = maybe (fail "SomeExchangeRate") pure =<< do src :: String <- Ser.decode dst :: String <- Ser.decode n :: Integer <- Ser.decode d :: Integer <- Ser.decode when (d == 0) (fail "denominator is zero") pure (MoneyI.mkSomeExchangeRate' src dst (n % d))