Skip to content

Instantly share code, notes, and snippets.

@danclien
Forked from bohde/Order.hs
Last active March 11, 2018 19:16
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 danclien/f3ea12d6c0b89289f8feb9cea56f094d to your computer and use it in GitHub Desktop.
Save danclien/f3ea12d6c0b89289f8feb9cea56f094d to your computer and use it in GitHub Desktop.
Example of Haskell code I see under tested a lot
module Order where
-- DBM is some Monad Transformer stack that allows us to talk to our DB (also a form of DI!)
placeOrder :: User -> OrderDetails -> DBM ()
placeOrder user details = do
-- Some users will have discounts for
(discount :: Maybe Discount) <- findRelevantDiscount user details
-- Create the specific order for this user with any discount
insertOrder $ mkOrder user details discount
-- Ensure any discount used won't be used again
forM_ discount $ redeemDiscount
-- Consider the properties we might want to test, e.g.
-- If there's a discount, and the order is place, the discount must be redeemed
-- if there's a discount, and the order errors, the discount must not be redeemed
-- These are things we can property test, except doing that against a
-- DB connection, makes this a hard thing to do. This is where MTL style type classes shine.
-- A naive function parameters version would look like
placeOrderFunction :: (User -> OrderDetails -> DBM (Maybe Discount)) -- findRelevantDiscount
-> (OrderRecord -> DBM ()) -- insertOrder
-> (Discount -> DBM ()) -- redeemDiscount
-> User -> OrderDetails -> DBM ()
-- An MTL style looks like this, and can be tested using monad-mock https://hackage.haskell.org/package/monad-mock
placeOrderMtl :: (MonadDB m) => User -> OrderDetails -> m ()
-- Record of functions
data DbEffects =
DbEffects
{ findRelevantDiscount :: User -> OrderDetails -> DBM (Maybe Discount)
, insertOrder :: OrderRecord -> DBM ()
, redeemDiscount :: Discount -> DBM ()
}
placeOrderRecord :: DbEffects -> User -> OrderDetails -> DBM ()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment