My earlier post on Haskell described a small DSL for calendar apps. In this post, I will show a very simple DSL (written in just 6 lines of code) to replace (a small portion of) GNU make utility. Earlier, I had attempted the GNU make replacement in Haskell without the use of DSL concepts.
At a very basic level, GNU make allows one to describe how a particular goal (or target) is made (generated using a set of shell commands) from a set of its dependencies. In Haskell, I should be able to describe this relationship like this:
return "test.c" ->> ccompile >>- "test.o" ->> link >>- "test.exe"
In other words, test.exe is made from test.o, which in turn is made from test.c.
The plumbing code can be written in a few of lines like this:
dep ->> cmd = \target -> dep >>= (\xdep -> (cmd xdep target) >> return target)
tcmd >>- target = (tcmd target) >> return target
ccompile dep target = system("gcc -c " ++ dep ++ " -o " ++ target)
link dep target = system("gcc " ++ dep ++ " -o " ++ target)
Notice, how the dataflow is made clear because of the notations used. In addition, the use of IO monad means you can keep on "linking" output of one stage to another. Compare and contrast this with the compiler based DSL using Ocaml described here.
For the sake of simplicity, I haven't added the code to check if the target is out of order with
respect to its dependency. And only one dependency per target is currently supported. These features however, are not very hard to add. As usual, your feedback is highly welcome and is sincerely appreciated. You can download the code from here.