Architecture of a Real World Haskell Application
onikudaki.net
onikudaki.net
With the imperative approach, you make liberal use of the IO monad. There's a lot of explicit reading from and writing to mutable storage. If you're doing this approach right, you mostly just use the IO monad for actual IO and threading; most of the real logic of the program is kept pure. This approach has the advantage of being familiar. And more importantly, it just plain works. It's how I tend to do things.
Yet I can't help but wonder if there's a better way. The above approach, while comfortable, leaves me with a bad taste in my mouth, like I'm somehow fighting against the language. I've often heard functional reactive programming (FRP) described as the best alternative. Though I remain skeptical. I'd be interested in opinions about the future of FRP.
We are able to subvert WPF databinding mechanisms to allow bindings to expressions as well as functions. The act of binding itself is still very imperative (and so, not very FRP-ish), but beyond that the programming styles are quite similar.
The result is that when writing FRP code, users have to manage two control flows: the 'logical' control flow, which is expressed via whatever FRP library they're using, and the actual control flow, which is the one provided by the language they're in. Languages would need good support for source-to-source transformation, or, alternatively, allow the compiler IR to be manipulated by libraries.
From the little I've played with Haskell, it appears the monadic binding operator (>>=) lets you do this, and the user writes code in an idiomatic, imperative-like manner. It is extremely impressive that this capability can be used to arbitrarily extend the language, while being a very small concept.
Edit: not sure if I had my terms right on the operator.
Regarding >>=: yes, it's the 'bind' operator, and yes, it is really impressive. This is why monads are hard: they're so abstract that they're good for _many_ things. It's also why they're so great.
FRP still feels like it's in the early stages, so I'm confident someone will find a better way to apply it. Right now it seems more palatable to non-bleeding-edge devs if you tailor it for specific use cases, rather than the whole thing at once. It may be the concept is too big to sell right now.
[1] http://research.microsoft.com/pubs/211297/managedtime.pdf
How'd you get hooked up with MS doing such cool stuff?
https://blogs.janestreet.com/breaking-down-frp/ http://people.seas.harvard.edu/~chong/abstracts/CzaplickiC13... http://www.testblogpleaseignore.com/wp-content/uploads/2012/...
I'm looking at a very similar problem (in form, not area), and literaly wondering that...
But back to your other point, sure you can write imperatively in Haskell and use IO and so on, but to really take advantage of the strengths of Haskell you need to write declaratively (i.e. functionally) and take advantage of the ways that helps you write things like GUIs (which are naturally declarative).
[0] dom callbacks actually swap! the nextState value so there are effects down there at the bottom of the view hierarchy, but that's react's fault for not letting you return the next state. e.g.
<input
value={this.state.a.b.c}
onChange={_.partial(mori.assoc_in, this.state, ['a', 'b', 'c'])} />It's amazing that we're back to immediate mode!
When I read about how to "architect" something I'm think about how to structure my Cabal file (a common pattern in my apps is a "library" of types, parsers, and utilities that are jointly used by multiple executables of the same program). I also think about structuring my tests, the naming and structure of module directory hierarchies, maybe also how to structure the program around the Main entry point.
I think there may also be a more interesting couple of "sub-articles" in this article: "How I built a server daemon in Haskell" and "How I built a GUI client in Haskell".
If architecture in the computing world consists of a system’s elements; the relationships between those elements; the attributes of the elements; and the attributes of the relationships, then architecture is not a timeline, process or stack description.
If you can't list the pros and cons relative to the other choices, I don't really consider that architecture - that's just doing what's familiar.
In the case of a computer program the "architecture" should be extremely well-thought out, idiomatic, and using established practices to produce a program that is easy to maintain, understand, and test.
I don't believe you need diagrams but in the case of Haskell, the types (if you design type-first) serve as one piece of the blueprint that is to become your program, your cabal file, directory structure, documentation (both user docs and API docs), and tests are all part of that blueprint.
In my experience, template haskell does not play well with profiling. If you were deriving lenses with TH, you could try writing them out yourself. That might solve this issue.
I would love to read more about mainstream functional language being used in scientific domains like CERN, ESA, NASA or SpaceX.
Then again, that might just be a wrong impression I got from reading, among other things, "Lisping at JPL" (http://www.flownet.com/gat/jpl-lisp.html)
I took a compiler class that was taught by the inventor (Dr. Daniel Cooke) of another functional language, SequenceL (see http://en.wikipedia.org/wiki/SequenceL). Cooke had funding from NASA to develop SequenceL because evidently NASA was/is very interested in program correctness (it's hard to guarantee correctness of a C++ program) and a simplified programming model.
The way Cooke explained it in class, SequenceL was born out of a desire for a simpler programming language (he believed that modern programming languages are too complex - so many require extra tooling to be productive) and a desire to make the implementation of a program as close as possible to the definition of the problem. He reasoned that if you could make an executable specification (i.e. the definition of the problem was executable), then all the mistakes that implementers make while implementing a program based on the problem specification/requirements would go away. In other words, since the definition of the problem would be the implementation, zero implementation mistakes would be made.
Interestingly enough, the first SequenceL interpreter and compiler was written in Haskell.
That's because the people making such decisions are not the ones qualified to do so (see the Lisping at JPL article you linked to). Their logic is probably along the lines of "if it's good enough for industry, ..." -- that's not an ellipsis, it is literally as far as the thought probably went.
Source: I worked at NASA for 4 years.
Note well, though, that the coding standards strictly limit the C++ features you can use. It's not done the way your average bunch of C++ code cowboys sling out an application.
F-35 is a similar example (worse because the contractor was probably at fault here: using C++ made the software system go way over budget on a cost-plus contract, and will likely result in larger maintenance contracts down the road. That's a win-win as far as the contractor is concerned...)
http://spectrum.ieee.org/riskfactor/aerospace/aviation/softw...
That is, many of the "safer" languages try to get by with disallowing explosive and dangerous constructs. With some of the more advanced tooling that is available and good discipline, one can still do some amazing things with them.
As far as I'm aware, Fortran and Algol are not widely used. But feel free to correct me.
What exactly do you know about Ada?
I have a friend who worked on autopilot obstacle avoidance for airplanes and I believe they did indeed use C++. It does seem a little primitive / bug-prone compared to some more high-level langs.
I agree that the existing tools are pretty limited