Thinking Functionally with Haskell
pragprog.com
pragprog.com
I agree, functional programming is great but sometimes I just see ideas being sold as "functional" that apply to programming in general. Splitting programs into smaller parts that are easily solvable and work in a predictable way is one of the most fundamental parts of coding.
Sure, that's not all there is to it, but I'm a little bothered that it's being marketed as the new thing.
List.map data ~f:(fun elem -> ...)
|! List.find ~f:( ... )
|! Option.map ~f:( ... )
(This is OCaml, not Haskell, but the syntax is similar.) The definition of the '|!' operator is quite simple: let (|!) x f = f x (|>) :: a -> (a->b) -> b
(|>) x f = f x
infixl 0 |>
There infixl 0 means infix operator with left associativity and 0 precedence.Then you can use all sorts of expressions inbetween:
(5 + 3 |> show) ++ " times" |> putStrLn
Also, tying this back to one of the article's ideas, this piping-like syntax for doing things really manages to take away the emphasis from the function and put it back on the data. It isn't all about functions after all!Eg:
(reduce + (take 10 (filter even? (map #(* % %) (range)))))
Can be expressed as:
(->> (range)
(map #(* % %))
(filter even?)
(take 10)
(reduce +))http://book.realworldhaskell.org/read/code-case-study-parsin...
(also you can read about the F# (|>) forward pipe, and there'll be operator precedence/associativity and thunk forcing issues)
For instance, look at his solution to FizzBuzz. Would you use a similar solution in ruby? He uses an infinite list, so if you naively translated it, you'd run out of memory. Instead, you'd have to explicitly use a generator in order to achieve a similar solution.
Of course, you can try always returning a generator in ruby, but that would be incredibly awkward because the built-in operators compute the entire result (like the + operator on lists). So, in practice, people intuitively avoid creating large intermediate results because it's wasteful, even in cases where that would simplify the code and make it more modular.
But in haskell, go ahead and use the large intermediate result, because it won't actually compute it before returning. It will just return a generator for the large intermediate result, and compute only the parts of that large result that are needed.
Books such as "Real World Haskell", the "gentle guide" and "Yet Another Haskell Tutorial" all manage the rather unbelievable feat of making many Haskell concepts unnecessarily complex, unintuitive and hard to understand -- not something you want for a language that is already on the complex side. For example, RWH goes into an absurdly complicated sample scenario (a parser, iirc) to introduce the reader to monads, and never slows down to go back to first principles. YAHT does the same thing.
Monads have a reputation for being hard to understand, but I think this is mostly the fault of the current literature; monads are conceptually simple, yet every book manages to botch their explanation, making the learning curve particularly steep for non-FP programmers.
About monads, seeing them outside of Haskell is a great way to see smaller steps. Articles like http://dorophone.blogspot.fr/2011/04/deep-emacs-part-1.html , or this video http://www.youtube.com/watch?v=ObR3qi4Guys
I hope it will help you
And I disagree a bit about RWH... I'm in the middle of it now I think it's great, filled with meaty examples that aren't too complicated at all and are generally pretty concrete. Maybe I'm just not far enough in yet? There are bits where it goes off into the weeds (the chapter on JSON goes so far as to fiddle about with character encoding IIRC) but I just can't imagine a PragProg book could do much better, without sacrificing depth.
That said, it is about programming in Haskell and not about programming with Haskell; hence this series of articles where I try to look at the wider picture and some pragmatic issues.
Personally, my "eureka" moment was reading the "IO Inside" [1] page on the Haskell wiki, which explains the IO monad in a way that made it click for me, as a imperatively-trained programmer. You can think of the IO monad as a way to force a compile-time dependency between I/O operations by having each IO-performing function take a "baton" value (the "IO" instance) as an argument, as well as return it. The explanation of how Haskell retains the appearance of purity in the face of impure I/O by passing an instance of RealWorld around is genius. That's a brilliant way to start out explaining monads, and it's something simple that you can use to explain the other monads such as the state monad (which the IO monad is built on).
I haven't tried the Hutton book yet.
What else would you like to see in such a book? http://forums.pragprog.com/posts/30455
Personally, I like the "Learn You A Haskell" style, of carefully and very gently building up the basic language, with examples that are as simple as possible and deal with only the issue being discussed. My problem with Real World Haskell is that it combines learning the language with building stuff. So when it gets to something like monads, there are way too much noise surrounding the core concept being explained. It's fine to show practical examples, but not everything should be built on them.
Aside from that, I like the practically-oriented stuff in RWH. I would like to see an article on doing concurrent, parallel, distributed systems (Erlang-style) in Haskell.
Monads are a useful technique, but they aren't everything!
A most insightful post, thank you very much.