As an exercise to wrap my brain around Haskell types and types, I am trying to implement a simple DDD / CQRS style solution. I model it directly after the implementation of Lev Gorodinski F # Simple CQRS .
I implemented a very simple aggregate Vehicle, which is a more or less direct port of the lion InventoryItemaggregate
module Vehicle where
data State = State { isActive :: Bool } deriving (Show)
zero = State { isActive = True }
type Mileage = Int
data Command =
Create String Mileage
| UpdateMileage Mileage
| Deactivate
deriving (Show)
data Event =
Created String
| MileageUpdated Mileage
| Deactivated
deriving (Show)
-- Define transitions from a command to one or more events
execute :: State -> Command -> [Event]
execute state (Create name mileage) = [Created name, MileageUpdated mileage]
execute state (UpdateMileage mileage) = [MileageUpdated mileage]
execute state Deactivate = [Deactivated]
-- Apply an event against the current state to get the new state
apply :: State -> Event -> State
apply state (Created _) = state
apply state (MileageUpdated _) = state
apply state Deactivated = state { isActive = False }
, , , , . Aggregate<'TState, 'TCommand, 'TEvent>, , Aggregate. Haskell , Typeclasses. , , , , .
, Aggregate Typeclass execute apply, -, , , . , Aggregate.
class Aggregate a where =
execute :: state -> command -> [event]
apply :: state -> event -> state
state, command event - , , Aggregate. , .
Typeclasses? , , Aggregate , ?
, Aggregate ?
@jberryman, MPTC , , :
{-
{-
module Aggregate where
class Aggregate state command event
| state -> command event, command -> state event, event -> state command where
execute :: state -> command -> [event]
apply :: state -> event -> state
zero :: state
makeHandler (load, commit) =
(\ (id, expectedVersion) command ->
do events <- load id
let state = foldl apply zero events
let newEvents = execute state command
commit (id, expectedVersion) newEvents)
Vehicle
instance Aggregate State Command Event where
execute = Vehicle.execute
apply = Vehicle.apply
zero = Vehicle.zero
script :
import Aggregate
import Vehicle
load :: Int -> IO [Event]
load id = do return [Created "Honda", MileageUpdated 15000]
commit (id, expectedVersion) events = putStrLn (show events)
handler = makeHandler (load, commit)
handler (1,1) Deactivate