Skip to content

Instantly share code, notes, and snippets.

@bohde
Last active March 11, 2018 19:13
Show Gist options
  • Save bohde/dd43768c8b9097c51bcc5bdcf0507afe to your computer and use it in GitHub Desktop.
Save bohde/dd43768c8b9097c51bcc5bdcf0507afe 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 ()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment