Plow Technologies is looking for an experienced Haskell developer who can lead software design. Deep understanding of the Haskell programming language is preferred. This person would be expected to work at all levels of our platform to optimize performance, reliability, and maintainability of our code base. We want the kind of programmer who makes everyone else better by: (1) designing application programming interfaces and libraries that speed up time of development; and (2) teaching others through direct interaction. The kind of skills that are desired for this position are rare, so remote work would definitely be an option. However, some direct interaction (including travel) should be expected.
Get information on how to apply for this position.
What are some papers that every Haskeller should read?submitted by incompetentacademic
[link] [33 comments]
What is the rationale in locating the standard modules in Haskell?
For instance, why Monoid, Functor, etc. are located in Data, while Applicative, Monad, Category, etc. are located in Control?submitted by BanX
[link] [10 comments]
Summary: Shake is a monadic build system, and monadic build systems are more powerful than applicative ones.
Several people have wondered if the dependencies in the Shake build system are monadic, and if Make dependencies are applicative. In this post I'll try and figure out what that means, and show that the claim is somewhat true.
Gergo recently wrote a good primer on the concepts of Applicative, Monads and Arrows (it is worth reading the first half if you are unfamiliar with monad or applicative). Using a similar idea, we can model a simple build system as a set of rules:rules :: [(FilePath, Action String)]
rules = [("a+b", do a <- need "a"; b <- need "b"; return (a ++ b))
,("a" , return "Hello ")
,("b" , return "World")
Each rule is on a separate line, containing a pair of the file the rule produces (e.g. a for the second rule) and the action that produces the files contents (e.g. return "Hello"). I've used need to allow a rule to use the contents of another file, so the rule for a+b depends on the files a and b, then concatenates their contents. We can run these rules to produce all the files. We've written these rules assuming Action is a Monad, using the do notation for monads. However, for the above build system, we can restrict ourselves to Applicative functions:rules = [("a+b", (++) <$> need "a" <*> need "b")
,("a" , pure "Hello ")
,("b" , pure "World")
If Action is applicative but not monadic then we can statically (without running any code operating on file contents) produce a dependency graph. If Action is monadic we can't generate a graph upfront, but there are some build systems that cannot be expressed applicatively. In particular, using a monad we can write a "dereferencing" build system:rules = [("!a", do a <- need "a"; need a)
,("a" , pure "b")
,("b" , pure "Goodbye")
To build the file !a we first require the file a (which produces the contents b), then we require the file b (which produces the contents Goodbye). Note that the first rule has changed b the content into b the file name. In general, to move information from the file content to a file name, requires a monad. Alternatively stated, a monad lets you chose future dependencies based on the results of previous dependencies.
One realistic example (from the original Shake paper), is building a .tar file from the list of files contained in a file. Using Shake we can write the Action:contents <- readFileLines "list.txt"
cmd "tar -cf" [out] contents
While it is the case that Shake is monadic, and that monadic build systems are more powerful than applicative ones, it is not the case that Make is applicative. In fact, almost no build systems are purely applicative. Looking at the build shootout, every build system tested can implement the !a example (provided the file a is not a build product), despite several systems being based on applicative dependencies.
Looking at Make specifically, it's clear that the output: input1 input2 formulation of dependencies is applicative in nature. However, there are at least two aspects I'm aware of that increase the power of Make:
- Using $(shell cat list.txt) I can splice the contents of list.txt into the Makefile, reading the contents of list.txt before the dependencies are parsed.
- Using -include file.d I can include additional rules that are themselves produced by the build system.
It seems every "applicative" build system contains some mechanism for extending its power. I believe some are strictly less powerful than monadic systems, while others may turn out to be an encoding of monadic rules. However, I think that an explicitly monadic definition provides a clearer foundation.