I finally grasped the use of monads while building linux images. To build the image, there were a series of steps that needed to run as root. If any step failed, the entire process needed to stop immediately or risk damaging my own filesystem. My script began looking like this:
res1 = execOrFail(cmd1, args)
res2 = execOrFail(cmd2, res1)
...
resn-1 = execOrFail(cmdn-1, resn-2)
finally(cmdn, resn-1)
It was at this point that I realized these steps could be more easily represented contained within a monad. Using a stop-on-failure-monad, this script would look more like this:
let open FailMonad in
monadicExec(cmd1, args) >>= fun res1
monadicExec(cmd2, res1) >>= fun res2
...
monadicExec(cmdn-1, resn-2) >>= fun resn-1
return monadicFinally(cmdn, resn-1)
I still didn't have a good understanding of what monads were though, so I
decided to start with the Maybe monad. Running this example (ocaml monad.ml
)
will produce no output because the assertions do not fail. So feel free to
study the source to come to a similar understanding.
In the future, I plan to apply this knowledge to create a stop-on-failure-monad and the appropriate monadic process execution functions necessary to idiomatically express the (safe) creation of a linux image. And, ideally, this stop-on-failure-monad could also become a stop-on-failure-and-rollback- monad. This way, my filesystem remains entirely safe despite performing a number of potentially dangerous commands as root.