Last active
January 19, 2024 10:47
-
-
Save ToJans/8219629 to your computer and use it in GitHub Desktop.
Haskell implementation of Greg Young's CQRS sample: https://github.com/gregoryyoung/m-r
Love the sheer elegance of Haskell; no need for all that infrastructure crap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Stii, on overall, it won't be that terse in C#, fo sure :)
Agreed!
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
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.