@@ -209,6 +209,7 @@ module Squeal.PostgreSQL.Binary
209209 , RowPG
210210 , LabelsPG
211211 -- * Storage newtypes
212+ , Money (..)
212213 , Json (..)
213214 , Jsonb (..)
214215 , Composite (..)
@@ -289,6 +290,7 @@ instance ToParam Word64 'PGint8 where toParam = K . Encoding.int8_word64
289290instance ToParam Float 'PGfloat4 where toParam = K . Encoding.float4
290291instance ToParam Double 'PGfloat8 where toParam = K . Encoding.float8
291292instance ToParam Scientific 'PGnumeric where toParam = K . Encoding.numeric
293+instance ToParam Money 'PGmoney where toParam = K . Encoding.int8_int64 . cents
292294instance ToParam UUID 'PGuuid where toParam = K . Encoding.uuid
293295instance ToParam (NetAddr IP) 'PGinet where toParam = K . Encoding.inet
294296instance ToParam Char ('PGchar 1) where toParam = K . Encoding.char_utf8
@@ -465,6 +467,7 @@ instance FromValue 'PGint8 Int64 where fromValue = Decoding.int
465467instance FromValue 'PGfloat4 Float where fromValue = Decoding.float4
466468instance FromValue 'PGfloat8 Double where fromValue = Decoding.float8
467469instance FromValue 'PGnumeric Scientific where fromValue = Decoding.numeric
470+instance FromValue 'PGmoney Money where fromValue = Money <$> Decoding.int
468471instance FromValue 'PGuuid UUID where fromValue = Decoding.uuid
469472instance FromValue 'PGinet (NetAddr IP) where fromValue = Decoding.inet
470473instance FromValue ('PGchar 1) Char where fromValue = Decoding.char
@@ -713,7 +716,34 @@ replicateMN
713716 :: forall x xs m. (All ((~) x) xs, Monad m, SListI xs)
714717 => m x -> m (NP I xs)
715718replicateMN mx = hsequence' $
716− hcpure (Proxy :: Proxy ((~) x)) (Comp (I <$> mx))
719+ hcpure (Proxy :: Proxy ((~) x)) (Comp (I <$> mx))
720+
721+{- | The `Money` newtype stores a monetary value in terms
722+of the number of cents, i.e. @$2,000.20@ would be expressed as
723+@Money { cents = 200020 }@.
724+
725+>>> import Control.Monad (void)
726+>>> import Control.Monad.Base (liftBase)
727+>>> import Squeal.PostgreSQL
728+>>> :{
729+let
730+ roundTrip :: Query_ (Public '[]) (Only Money) (Only Money)
731+ roundTrip = values_ $ parameter @1 money `as` #fromOnly
732+:}
733+
734+>>> let input = Only (Money 20020)
735+
736+>>> :{
737+void . withConnection "host=localhost port=5432 dbname=exampledb" $ do
738+ result <- runQueryParams roundTrip input
739+ Just output <- firstRow result
740+ liftBase . print $ input == output
741+:}
742+True
743+-}
744+newtype Money = Money { cents :: Int64 }
745+ deriving (Eq, Ord, Show, Read, GHC.Generic)
746+type instance PG Money = 'PGmoney
717747
718748{- | The `Json` newtype is an indication that the Haskell
719749type it's applied to should be stored as a `PGjson`.