Skip to content

Instantly share code, notes, and snippets.

Last active March 26, 2018 15:46
What would you like to do?
Haskell implementation of Greg Young's CQRS sample: Love the sheer elegance of Haskell; no need for all that infrastructure crap
module InventoryItems(Command(..), Event(..), handle) where
import Data.Maybe(isJust)
type Id = String
type Name = String
type Amount = Int
data Command = CreateInventoryItem Id
| RenameInventoryItem Id Name
| RemoveItemsFromInventory Id Amount
| AddItemsToInventory Id Amount
| DeactivateInventoryItem Id
deriving (Show)
data Event = InventoryItemCreated Id
| InventoryItemRenamed Id Name
| ItemsRemovedFromInventory Id Amount
| ItemsCheckedInToInventory Id Amount
| InventoryItemDeactivated Id
deriving (Show, Read)
data Item = Item { itemId :: Id
, itemActivated :: Bool
handle :: [Event] -> Command -> [Event]
handle events command =
handle' item command
where item = apply events
handle' maybeItem (CreateInventoryItem id)
| itemExists = error "item already created"
| otherwise = [InventoryItemCreated id]
where itemExists = isJust maybeItem
handle' Nothing _command = error "please create the item first"
handle' (Just item) (DeactivateInventoryItem id)
| deactivated = error "already deactivated"
| otherwise = [InventoryItemDeactivated id]
where deactivated = not (itemActivated item)
handle' (Just Item {itemActivated = False}) _command = error "item is deactivated"
handle' (Just item) (RenameInventoryItem id name)
| invalidName = error "newName"
| otherwise = [InventoryItemRenamed id name]
where invalidName = name == []
handle' (Just item) (RemoveItemsFromInventory id amount)
| invalidAmount = error "can't remove negative amount from inventory"
| otherwise = [ItemsRemovedFromInventory id amount]
where invalidAmount = amount <= 0
handle' (Just item) (AddItemsToInventory id amount)
| invalidAmount = error "must have an amount > 0 to checkin to inventory"
| otherwise = [ItemsCheckedInToInventory id amount]
where invalidAmount = amount <= 0
apply events = foldl apply' Nothing events
apply' Nothing (InventoryItemCreated id) = Just (Item id True)
apply' (Just item) (InventoryItemDeactivated id) = Just (item {itemActivated = False})
apply' (Just item) _ = Just item
Copy link

yevhen commented Jan 2, 2014

There is no neeed for any of that infrastructure crap in C# either, even including DelegateAdjuster. I believe that Greg was just having fun (trolling actually). All that crap, including DelegateAdjuster could be substituted by using dynamic and casting to object.

Copy link

yevhen commented Jan 2, 2014

Stii, on overall, it won't be that terse in C#, fo sure :)

Copy link

ToJans commented Jan 3, 2014


Copy link

This is more than elegance, it's an electronic poem :) Just a fantastic comparison.

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