
Hello, I've got a problem, in short my haskell code sucks. While it does work and I do manage to use higher-orderish aspects quite extensively to make my code more concise it still is nowhere abstract, always concrete and thus always with lots of boilerplate. Oh I have gotten better compared to when I started but on the abstraction slope I'm still stuck. So fellows, what is the next stop on my road to enlightenment? I really think I need best to start from scratch. I think I'm sufficiently familiar now with most of Haskell's technicalities but how do I climb the ladder of abstraction? Günther

2010/2/14 Günther Schmidt
So fellows, what is the next stop on my road to enlightenment? I really think I need best to start from scratch. I think I'm sufficiently familiar now with most of Haskell's technicalities but how do I climb the ladder of abstraction?
A couple of suggestions: - Read the code of other people. You will learn things from this. - Use hLint on your code. - Read "The Monad Reader", Brent's excellent typeclassopedia article for instance. You must know the tool box before you can apply it. - Read some of the papers that introduce various new abstract code concepts. The trick is to ask the question "Can this apply to some of my code?" for each of them. -- J.

* On Sun, Feb 14 2010, Günther Schmidt wrote:
So fellows, what is the next stop on my road to enlightenment? I really think I need best to start from scratch. I think I'm sufficiently familiar now with most of Haskell's technicalities but how do I climb the ladder of abstraction?
Read more code. Write more code. Repeat. Regards, Jonathan Rockway -- Just "another Haskell hacker"

Hi Günther Promoting a slightly contrary view, I'm not sure that abstraction should be a goal in itself. Richard Gabriel makes a point of valuing 'habitable' code over abstract code in his 'Patterns of Software' book (free from his website now that it's out of print). Habitable code being code you can live with - understand and modify. I'd look to making the code readable in the first instance, if you are working from a published algorithm can you code it line-for-line (hiding supplementary definitions in where-clauses or helper functions when necessary)? Or, if you are working from your own algorithms, maybe you need to work a little bit more on factoring the algorithm before it comes to writing the actual code. Best wishes Stephen

On Feb 14, 2010, at 4:38 AM, Günther Schmidt wrote:
I've got a problem, in short my haskell code sucks. While it does work and I do manage to use higher-orderish aspects quite extensively to make my code more concise it still is nowhere abstract, always concrete and thus always with lots of boilerplate.
There is a such a thing as too much higher-ordered-ness. Every time you introduce a new higher order dispatch mechanism, you go through many of the same steps, and produce "slightly incompatible" interfaces. You're basically defining plumbing, which you might have to plumb into your existing plumbing. Boilerplate city. Instead of looking for a higher-order solution to your problem, look for a normal form to express abstract terms that solve your problem. The higher-order solution will become "obvious" when you have the right normal forms (because now you know what you're quantifying over) For example, algebraic data types are a natural encoding for tree-like structures. They can even contain things. Monads are an encoding for tree-like structures with an interface to the things the nodes contain. I'm not saying you need to use monads. I'm saying you should use them when they are the right normal form. Unfortunately, boilerplate is kind of a fact of life in Haskell, unless you use things like TemplateHaskell or SYB. After making all our nice orthogonal classes and data types in sensible normal forms, we need to join these classes and types, with functions and class instances. Taking big types down a chain of type classes is no fun. But at least all that complexity is kept in one sensible place. One thing I wish GHC would do better is deal with cyclical module dependencies more flexibly. More flexibility would mean letting us organize our code by the normal form it embodies, as opposed to the modules/types it uses. That makes code look a lot less boilerplate- ish, since the "irrelevant" but important bits can all go together.

Well I just noticed that the boilerplate part consists of this: Import data by selecting fields from a table, feed them into some sort of internal data structure for later querying, times 12. All this involves quite a bit of boilerplate. Yeah, I guess I could abstract here a little. Günther Am 14.02.10 23:37, schrieb Alexander Solla:
On Feb 14, 2010, at 4:38 AM, Günther Schmidt wrote:
I've got a problem, in short my haskell code sucks. While it does work and I do manage to use higher-orderish aspects quite extensively to make my code more concise it still is nowhere abstract, always concrete and thus always with lots of boilerplate.
There is a such a thing as too much higher-ordered-ness. Every time you introduce a new higher order dispatch mechanism, you go through many of the same steps, and produce "slightly incompatible" interfaces. You're basically defining plumbing, which you might have to plumb into your existing plumbing. Boilerplate city.
Instead of looking for a higher-order solution to your problem, look for a normal form to express abstract terms that solve your problem. The higher-order solution will become "obvious" when you have the right normal forms (because now you know what you're quantifying over) For example, algebraic data types are a natural encoding for tree-like structures. They can even contain things. Monads are an encoding for tree-like structures with an interface to the things the nodes contain. I'm not saying you need to use monads. I'm saying you should use them when they are the right normal form.
Unfortunately, boilerplate is kind of a fact of life in Haskell, unless you use things like TemplateHaskell or SYB. After making all our nice orthogonal classes and data types in sensible normal forms, we need to join these classes and types, with functions and class instances. Taking big types down a chain of type classes is no fun. But at least all that complexity is kept in one sensible place.
One thing I wish GHC would do better is deal with cyclical module dependencies more flexibly. More flexibility would mean letting us organize our code by the normal form it embodies, as opposed to the modules/types it uses. That makes code look a lot less boilerplate-ish, since the "irrelevant" but important bits can all go together.

Hello,
2010/2/14, Günther Schmidt
Hello,
I've got a problem, in short my haskell code sucks. While it does work and I do manage to use higher-orderish aspects quite extensively to make my code more concise it still is nowhere abstract, always concrete and thus always with lots of boilerplate.
Oh I have gotten better compared to when I started but on the abstraction slope I'm still stuck.
So fellows, what is the next stop on my road to enlightenment? I really think I need best to start from scratch. I think I'm sufficiently familiar now with most of Haskell's technicalities but how do I climb the ladder of abstraction?
It's actually okay: you come up with abstractions as a result of abstracting things out, :) not the other way round. I'd advise you to read "How To Design Programs". Unrelated to Haskell, it shows a bunch of nice examples of abstraction, including the steps required to get there, with motivation and justifications. The books is aimed at beginners in programming, but don't let that discourage you: it has good ideas to share. Cheers, Artyom Shalkhakov

Günther Schmidt wrote:
I've got a problem, in short my haskell code sucks. While it does work and I do manage to use higher-orderish aspects quite extensively to make my code more concise it still is nowhere abstract, always concrete and thus always with lots of boilerplate.
Oh I have gotten better compared to when I started but on the abstraction slope I'm still stuck.
So fellows, what is the next stop on my road to enlightenment? I really think I need best to start from scratch. I think I'm sufficiently familiar now with most of Haskell's technicalities but how do I climb the ladder of abstraction?
As others said, there are already a few existing abstractions that you can take advantage of, like applicative functors, functional references (aka data-accessor) or monads; it pays to know them well. Other than that, many abstractions will probably be some kind of domain specific language. Since those are by definition specific to the problem domain, it's hard to give general advice. I'd suggest to learn from examples like Paul Hudak. The Design of a Pretty-printing Library. http://citeseer.ist.psu.edu/hughes95design.html Philip Wadler. A prettier printer. http://decenturl.com/homepages.inf.ed/wadler-98-prettier-printer Simon Peyton Jones, Jean-Marc Eber, Julian Seward. Composing contracts: an adventure in financial engineering. http://decenturl.com/research.microsoft/spj-financial-contracts Regards, Heinrich Apfelmus -- http://apfelmus.nfshost.com
participants (7)
-
Alexander Solla
-
Artyom Shalkhakov
-
Günther Schmidt
-
Heinrich Apfelmus
-
Jesper Louis Andersen
-
Jonathan Rockway
-
Stephen Tetley