Well, I don’t have project, I’m experimenting in one file :D, It basicali is mini cqrs system where you have domain functions create, increment, decrement, add
that generate events that they should by applied on state using function mutate
and I’m triing to create command handler for it using monads (using state to store actual state and after every domain function mutate it and also writer to store all events that been generated during execution, function test()
is returning array of solutions, I managed to solve it without writer using chain (function exec2):
defmodule Witch do
use Witchcraft.Monad
use Witchcraft.Chain
import Algae.State
import Algae.Writer
def create(agg) do
if is_nil(agg) do
[:created]
end
end
def increment(agg) do
if agg < 10 do
[{:added, 1}]
end
end
def decrement(agg) do
if agg > 0 do
[{:subsctracted, 1}]
end
end
def add(agg, count) do
if agg < 10 do
[{:added, count}]
end
end
def subsctract(agg, count) do
if agg > 0 do
[{:subsctracted, count}]
end
end
def mutate(_agg, :created) do
0
end
def mutate(agg, {:added, count}) do
agg + count
end
def mutate(agg, {:subsctracted, count}) do
agg - count
end
def mutate(agg, events) when is_list(events) do
Enum.reduce(events, agg, &mutate(&2, &1))
end
def test() do
[
put(1) |> run(0),
modify(& &1 + 1) |> run(0),
get() |> run(0),
get(& create/1) |> run(nil),
monad %Algae.State{} do
events <- get(& create/1)
modify & mutate(&1, events)
nevents <- get(& increment/1)
modify & mutate(&1, nevents)
return events ++ nevents
end
|> evaluate(nil),
monad %Algae.State{} do
events1 <- exec(& create/1)
events2 <- exec(& increment/1)
events3 <- exec(& increment/1)
return events1 ++ events2 ++ events3
end
|> run(nil),
exec1(& create/1) >>> exec2(& increment/1) >>> exec2(& increment/1) |> evaluate(nil),
Witchcraft.Chain.chain do
[]
exec2(& create/1)
exec2(& increment/1)
exec2(& increment/1)
count <- [1, 2, 3]
exec2(& add(&1, count))
end,
monad %Algae.State{} do
exec(& create/1)
exec(& increment/1)
end |> evaluate(nil),
monad %Algae.Writer{} do
events <-
monad %Algae.State{} do
events <- get(&create/1)
modify & mutate(&1, events)
return events
end
tell(events)
events <-
monad %Algae.State{} do
events <- get(&increment/1)
modify & mutate(&1, events)
return events
end
tell(events)
end
|> Algae.Writer.run(),
tell("test"),
new(1, "test") |> listen()
]
end
def exec(callback) do
monad %Algae.State{} do
events <- get(callback)
modify & mutate(&1, events)
return events
end
end
def exec1(callback) do
exec2(callback).([])
end
def exec2(callback) do
fn old ->
monad %Algae.State{} do
events <- get(callback)
modify & mutate(&1, events)
return old ++ events
end
end
end
end