And that’s really the point: I don’t need to pick up on a slightly different syntax and somewhat different environment for representing the same kinds of constructs I’m used to. There might be a small number of new and interesting concepts to inspire you, but for the most part they are “me too” on the current engineering paradigms and if anything leaning back to simplicity and leaving out features that could separate the top coders from the mundane (since the latter will need to maintain the code later).
But brushing up on techniques and ways of thinking that are truly different helps improve your engineering skills in general.
For example, a number of years ago I re-implemented a piece of code for laying out images on a page. The old code had been extended, fixed, patched up, and “maintained” to the point where it was impossible to understand what was going on. Cleaning it off would be a temporary measure if new requirements and changes continued as they always have. So, I approached it using concepts from functional programming, even though written in (an early version) of C♯. Defining the constraints and properties of the desired layout, rather than a spaghetti flowchart of patched procedures that manipulate all the state variables, means at the very least that it could be extended without breaking it. The logic was unfathomable because of state dependance—what happened before affects what some block of code will do to it next. So I had no state variables at all. The layout rectangle of an item was expressed as a pure function, and the various bottom level functions could easily be reviewed for correctness.
Functional programming has been making inroads into mainstream programming, with otherwise procedural and OO languages acquiring features friendly to techniques gained from FP.
In particular, template metaprogramming in C++ (which I’ve seen described as “a slow descent into madness”) exists because the template system is a Turing-complete, albeit crudely primitive, functional programming language.
Meanwhile, I’ve read that monads have a strange property: anyone who comes to understand it loses any ability to explain it to others. That reminds me of the science fiction novel Babel-17. In fact as in the story, language influences thought and perception, which is what I was getting at earlier in this essay. Being a writer on programming topics, I thought I’d take that as a challenge. Maybe I’ll write a truly good explanation of monads; or maybe it will end up joining the hundreds of others that are are either indecipherable or lack proper deep meaning. (See also monad tutorial fallacy)
A lot of what I see of beginners’ Haskell examples remind me of Prolog.
Anyway, I just tried crafting my first Haskell snippet, other than things like 2+2 or copying lines from the book. Project Euler, problem 1,
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.
Here is the session from the interactive environment:
Prelude> [x | x <- [1..10], x `mod` 3 == 0]
Prelude> [x | x <- [1..10], x `mod` 3 == 0 || x `mod` 5 == 0]
Prelude> sum [x | x <- [1..10], x `mod` 3 == 0 || x `mod` 5 == 0]
Prelude> sum [x | x <- [1..9], x `mod` 3 == 0 || x `mod` 5 == 0]
Prelude> sum [x | x <- [1..999], x `mod` 3 == 0 || x `mod` 5 == 0]
Prelude> [x | x <- [1..999], x `mod` 3 == 0 || x `mod` 5 == 0]
After expressing the shorter example, first to get the list of terms to see if that part is right thus far, and then summing them, I changed the bound to the larger value and got an answer of 233168. Just to see what it was, I then backed off the final sum to get the list of terms.
So far, so good.