Skip to content

Instantly share code, notes, and snippets.

@tvlooy
Forked from ToJans/InventoryItems.hs
Last active August 29, 2015 14:12
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 tvlooy/f2020f66a710da9496f1 to your computer and use it in GitHub Desktop.
Save tvlooy/f2020f66a710da9496f1 to your computer and use it in GitHub Desktop.
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment