Spreadsheet-like programming in Haskell
haskellforall.com
haskellforall.com
This is one of the downsides of Haskell; with so much emphasis on abstraction, code often ends up being just that: so damn abstract that it's practically inscrutable except to the very few who are familiar with what's going on. I guess this article was written for an audience with very broad and detailed knowledge of some complicated Haskell libraries -- meaning it's not so important that anyone else be able to make head or tails out of what he's talking about. Which is ok, but it does add to the impression that Haskell is an exclusive club.
Also, this part sticks out as confusing: The type signature of `example` does not include IO (unless Updatable has IO on under the hood), and yet the language above suggests that it will change, i.e. that it is mutable:
> example will update every time lastLine or seconds updates, caching and reusing portions that do not update. For example, if lastLine updates then only the first field of Example will change. Similarly, if seconds updates then only the second field of Example will change.
Can someone clear this up for me?
Suppose you have three data nodes, or cells: A, B, C, and D. A holds the value 5, B holds 3, C is defined as A+B, and D is defined as B*C. In a spreadsheet, changing cell A will automatically update C, because C directly depends on A. It will also update D because it transitively depends on B through C, and C has changed. This library (and the Clojure one I mentioned in my other post) lets you define data structures which behave the same way.
In a pure environment, you can emulate this using only functions. In a non-pure environment, automatically updating values can be quite nice. You use this to implicitly trigger linked behaviors. In a UI, this could mean changing the state of several elements in response to some input without having to explicitly say updateElementA(), updateElementB(), and so on.
http://www.haskellforall.com/2014/04/model-view-controller-h...
http://www.haskellforall.com/2013/08/composable-streaming-fo...
It might seem like too much abstraction until you realize that the alternative would be the following obtuse type:
data Updatable a = forall x y . Updatable (forall r . ((x, x -> y -> x, x -> a, STM (Maybe y)) -> IO r) -> IO r))
That's what you get if you completely expand out the implementation of `Updatable`. This is why I build up these abstractions from smaller composable pieces (i.e. `Fold` and `Managed` and `Controller`), each of which is intrinsically useful in isolation.However, I think if you are trying to understand how `Managed` and `Controller` and `Fold` work all in one go, you're going about it the wrong way. Haskell lends itself really well to abstracting over the implementation by specifying mathematical equations inspired by category theory that the implementation obeys. This is not the fake kind of abstraction that other languages promise but never actually deliver (i.e. abstractions that leak and forces you to read source code, often times several layers deep). Rather, everything you need to know about the abstraction layer immediately underneath you is completely summarized by a succinct set of equations that you can then use to prove a new set of equations for the immediately following layer. This post gives an example of this layered proof process:
http://www.haskellforall.com/2013/12/equational-reasoning.ht...
By composing these small, correct-by-construction layers of equations you can grow to arbitrary complexity while always preserving correctness. More importantly, you never need to reason about more than a single layer at a time since you've decoupled each layer's correctness proofs from each other. Contrast this with other languages where you often have to reason simultaneously over many layers of abstractions to debug difficult issues or prove correctness.
To answer the meat of your question, all you really need to know to understand how `Updatable` works is that:
* `Fold e` is an `Applicative`, for all `e`
* `Managed (Controller e)` is a `Monoid`, for all `e`
* `onLeft` and `onRight` are `Applicative` homomorphisms (this detail is noted in the library source code but I omitted it from the blog post)
Those four properties concisely summarize everything you need to know about every abstraction underneath `Updatable`. If you approach this correctly, there is no need to dig into their source code further to understand how they work. Truthfully, I would love if you were to dig into their source code to learn how they work, but if you really want to level up as a programmer then you need to start thinking more abstractly, layer-by-layer, instead of trying to fit the entire programming stack into your head all at once.
It's generally useful for writing reactive, incremental, iterative programs.
Frustrating.
I thought you meant you saw some significant barriers to a full implementation or something fundamentally different in the underlying model that was not spreadsheet like.
So on the surface I think the superficial thrust of this is rather blunted.
But, and it's a really big but, software is the new literacy. And it is long and hard to learn to read and write, but we force our children to do it as a society because of the orders of magnitude benefits.
And so the same will become true of software - but not at the paltry expressive level of say, pg's Blub language - but at something Haskell is trying for.
I say there are three kinds of stages of sophistication for a person or a company - not coding, automating and compiler.
We want our children to be operating at the compiler level - so we want them to be using the languages Haskell will evolve into.
Now where did I put my copy of SICP?
Edit: Blub language not Blah...
My approach is inspired by join calculus which is centered on the concept of waiting on a set of signals/cells to trigger a reaction (I ignore the concurrency capabilities of join calculus which make it a bit more complex). It seems to me that FRP takes the long route to achieve this since its focused on event handling.
Anyhow, this can be easily achieved with a simplified cactus stack where each stack "frame" holds a reference to its parent so that it notifies its parent when its value is set, then when all of the stack frames are ready the procedure associated to it is triggered.
This type of stack has some interesting capabilities including memory friendly infinite recursion and compound-key data structures. I believe that it has potential for artificial intelligence and the development of modern dataflow languages.
And I'm sure the high frequency traders using it would chuckle to hear that they are "academics".
In particular, the cynical part of my mind wonders if it's simply because you can't read the code, and because of that haven't really bothered to follow the argument. I'm sure you must have deeper reasons that that, and I, for one, would appreciate an explanation of your reasoning.
If you're going to talk about the power of a language you have to allow the use of language that talks about that power. To talk about what you can do in Haskell beyond toy problems you need to allow people to use more than just toy language.
If readers aren't willing to do any work, its tough to help them learn anything new.
https://github.com/scalaz/scalaz/blob/scalaz-seven/core/src/...
Do they differ in some drastic way? (Note: I'm not super familiar with the Haskell version.)