Hi there,
Here are two files: StringWriter.elm and CmdWriter.elm. (edit: links no longer work)
Both are implementations of the Writer monad. In particular, lets look at the two implementations of andThen
:
andThen : (state1 -> StringWriter state2 ) -> StringWriter state1 -> StringWriter state2
andThen fun ( a, out ) =
let
( newA, newOut ) =
fun a
in
( newA
, out |> (\c1 c2 -> c2 ++ c1) newOut
)
andThen : (state1 -> CmdWriter state2 out) -> CmdWriter state1 out -> CmdWriter state2 out
andThen fun ( a, out ) =
let
( newA, newOut ) =
fun a
in
( newA
, out |> (\c1 c2 -> Cmd.batch [c1,c2]) newOut
)
As you can see, we are using c2 ++ c1
for the StringWriter and Cmd.batch [c1,c2]
for the CmdWriter. Additionally, CmdWriter has two type variables, whereas StringWriter has just one. Other than that, the two implementations are identical.
This is done by generating Elm files from templates using a little program
Here is the input that generated the two files:
{
"generateInto": "elm-gen/generated",
"templatesFrom": "elm-gen/templates",
"moduleBase": "Gen",
"modules": {
"StringWriter": {
"Writer": {
"imports": [],
"output": {
"type": "String",
"polymorphic": false,
"empty": "\"\"",
"append": "(\\c1 c2 -> c2 ++ c1)"
}
}
},
"CmdWriter": {
"Writer": {
"imports": [],
"output": {
"type": "Cmd",
"polymorphic": true,
"empty": "Cmd.none",
"append": "(\\c1 c2 -> Cmd.batch [c1,c2])"
}
}
}
}
}
Isnât this awesome?
This project is actually just a few hours old, but the things that can be done with thisâŠ
I mean, the writer monad is just a showstopper. The real value behind this tool comes from the Enum and Record templates.
It will properly take a month or so until I can bring this tool into an alpha stage and officially announce it. But for now, I just wanted to share my excitement with you.