How to think like a functional programmer?

Hi Folks, I am working on a project and am trying hard to write the code in a functional style. Sadly, upon reviewing what I've written, I realize that I am not succeeding. I just devised a recipe for solving the problem and then created functions corresponding to steps in the recipe. I am still thinking imperatively, not functionally. Is there a book or article that describes how to approach problems from a functional mindset? How did you "flip the switch" in your brain to the functional mindset? /Roger

On 26 May 2011 18:27, Costello, Roger L.
I am working on a project and am trying hard to write the code in a functional style.
How did you “flip the switch” in your brain to the functional mindset?
What's the project? Maybe we can offer some "how we'd do it" bits of advice. I personally got some insights after some Haskellers rewrote a couple of my functions in the way they'd do it when I was beginning.

Sadly, upon reviewing what I’ve written, I realize that I am not succeeding. I just devised a recipe for solving the problem and then created functions corresponding to steps in the recipe. I am still thinking imperatively, not functionally.
Is there a book or article that describes how to approach problems from a functional mindset?
How did you “flip the switch” in your brain to the functional mindset? Examples. Read lots of code. Don't worry if you don't understand all of it. But don't just 'look' at it, run it in your mind. Programming is like writing in that just like a novel writer, you read 10x the amount you write. Rewrite the same code as you learn, note the differences.
Others will provide better recommendations than I wtr recommended sources. Think of your problem not in term of what it does, but what data it handles, and what it does to it. Design your program as a set of boxes consuming and producing data, then implement the boxes as functions. If your data needs to be transformed in succesive steps, that's sequential computation and part of the problem's nature, not necessarily a result of an imperative mindset. You can implement it with composed functions. Functional programming can free you from having to deal with certain 'bookkeeping' aspects of imperative programming, but it doesn't free you from having to design a solution to the program. e.g mapping over a sequence is better than having to write a loop and control iteration, but you still had to think "do/apply X to all these Y". good luck, Iñaki Garay. -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/GMU d- s:- a25 C++ UL+++ P--- E- W+ PS+++ PE- Y+ t++ 5+ tv- b++ DI+ D--- G e h! r y++ ------END GEEK CODE BLOCK------

On 26 May 2011 17:27, Costello, Roger L.
How did you “flip the switch” in your brain to the functional mindset?
For me, one thing that changed is that I now tend to focus more on the data *transformations* rather than on the data itself. I tend now to group similar transformations into modules. (Before, as an OO programmer, I would have thought of each module as a class of objects, so I would have grouped everything that acts on that object or that the object does into one class.) Eventually you want to build a chain of transformations that takes the input and produces the output you want. Another way to visualise it: Instead of thinking of the steps to solve a problem, think of the solution as a series of definitions. Write a definition (an equationof of the result you want in terms of simpler things. Write definitions of those simpler things in terms of things that are even simpler. And so on, until you can build a pyramid of definitions that defines the final output in terms of the input. I found it helpful to post a few small code samples on this forum, and to ask for suggestions for a better implementation. Good luck!

On 26 May 2011 17:27, Costello, Roger L.
wrote: How did you “flip the switch” in your brain to the functional mindset?
What I found important is the following: - to make your functions declaritive, then you can improve on them later - do what Geraint Jones has called "wholemeal programming"; it helps prevent a disease called "indexitis" and encourages lawful program construction (from "Pearls of Functional Algorithm Design", Richard Bird, 2010) -- -- Regards, KC

On 5/26/11 7:55 PM, KC wrote: >> On 26 May 2011 17:27, Costello, Roger L.wrote: >>> How did you “flip the switch” in your brain to the functional mindset? > What I found important is the following: > - to make your functions declaritive, then you can improve on them later > - do what Geraint Jones has called "wholemeal programming"; it helps > prevent a disease called "indexitis" and encourages lawful program > construction (from "Pearls of Functional Algorithm Design", Richard > Bird, 2010) "Functional languages excel at wholemeal programming, a term coined by Geraint Jones. Wholemeal programming means to think big: work with an entire list, rather than a sequence of elements; develop a solution space, rather than an individual solution; imagine a graph, rather than a single path. The wholemeal approach often offers new insights or provides new perspectives on a given problem. It is nicely complemented by the idea of projective programming: first solve a more general problem, then extract the interesting bits and pieces by transforming the general program into more specialised ones." http://www.comlab.ox.ac.uk/ralf.hinze/publications/ICFP09.pdf

On 5/26/11 6:27 PM, Costello, Roger L. wrote:
Hi Folks,
I am working on a project and am trying hard to write the code in a functional style.
Sadly, upon reviewing what I've written, I realize that I am not succeeding. I just devised a recipe for solving the problem and then created functions corresponding to steps in the recipe. I am still thinking imperatively, not functionally.
Is there a book or article that describes how to approach problems from a functional mindset?
How did you "flip the switch" in your brain to the functional mindset?
Hi Roger, reminding oneself to take it literal, I found can be quite clarifying. At the core of it, I found it helps to "avoid thinking state", i.e. putting stuff into variables. If you find yourself doing that a lot, it's a sign for the wrong track. You'll find, again and again, you don't need to keep that state. Just pass up the result of a call. Inversely, avoid "lines that do not deliver a result", which "just do something". Or, to be precise, note when you don't use a result. Taking "functional programming" literal, you'd try thinking about the entire problem as but nested function calls with no intermediary state holders, rather than "implicitly tacting state tables", if that makes any sense. Best, Henning
/Roger
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

"Costello, Roger L."
I am working on a project and am trying hard to write the code in a functional style.
Sadly, upon reviewing what I've written, I realize that I am not succeeding. I just devised a recipe for solving the problem and then created functions corresponding to steps in the recipe. I am still thinking imperatively, not functionally.
Is there a book or article that describes how to approach problems from a functional mindset?
How did you "flip the switch" in your brain to the functional mindset?
I don't know whether there is a book, but I can tell you how I did it. Just like you and most others I came from an imperative background. First of all, don't try too hard. It can be very frustrating, when you are a beginner. There is nothing wrong with writing nonidiomatic code at the beginning. I will give you some basic rules you can follow to get fluent in Haskell: * Understand the syntax It happens to a lot of newbies that they get overwhelmed and totally confused by the number of symbols, which they have never seen before in other languages. Don't panic! Most of these symbols are ordinary functions. If you disregard those, you will have a handful of symbols left, likely even less than in other languages. Most of those are just syntactic sugar for, again, regular functions and function applications. Haskell is an incredibly simple language at its core. * Understand the basics of the type system Haskell's type system is very sophisticated and can take months or years to understand fully, especially when you start working with some of the type system extensions. But this pays off! Once you know how to read and write type signatures you will find that most functions together with their type signatures are fairly self-explanatory. I constantly learn the interface of new libraries by just looking at the types. The type system will also improve the safety of your programs up to the point where you will experience a strange sensation: Once your program passes the compiler, it usually works! Finally you will find that it is advantageous to write a type signature, before writing the corresponding definition. For example for a function to add two integers using only increment (succ) and decrement (pred), first write its type signature: add :: Integer -> Integer -> Integer And only after that write its definition: add x 0 = x add x y = add (succ x) (pred y) Firstly this will prepare your mind for the implementation, because you know what structure the function has to have. Secondly it will prevent a broad class of bugs. * Know your tools This is about the most important rule, because in Haskell you have an incredible amount of abstractions and design patterns, which you simply cannot have in most other languages. The introduction of laziness alone gives you many new design patterns you probably have never seen before. Of course in the beginning you will use the tools you know from other languages, as far as applicable to Haskell. But the more you work with it, the more you will learn the 'other' tools. And once you learned them, other languages will really annoy you. ;) * Understand the language semantics Finally this last point will give you the in-depth understanding of what is going on under the hood. It will help you understand the tools you are using. You will learn what "non-strict" actually means, what the "bottom" value is, how to prevent stack/heap overflows, etc. Now don't just search for tutorials or books. Instead, write applications! Haskell can be learned best by writing actual code. I will give you a very interesting problem to begin with. The n-th Mersenne number is 2^n - 1. There are certain Mersenne numbers, which are prime numbers. For this kind of numbers there exists a fast primality test, which is also used in the large distributed prime number searches like GIMPS. It's called the Lucas-Lehmer primality test and involves generating an infinite sequence of numbers and picking a certain element from it. This task is not just a great opportunity to learn functional thinking, but in particular Haskell thinking, because you would solve the problem differently in other functional languages. In an imperative approach you would write a loop, which destructively updates a variable a certain number of times, before reading its value. The first translation of this to Haskell is to write a recursive function, which uses function parameters and recursion as a replacement for destructively updated variables. This is not really an improvement, as you will write essentially the same code, but with recursive calls instead of destructive updates. You got rid of the side effects, but not of the general imperative idea of the computation. Now comes the most important third point: Know your tools! In this case you have a tool, which you won't find in most other languages: infinite data structures, in particular infinite lists. Using the 'iterate' combinator you can make a direct translation of this infinite sequence. You write an infinite list. Then using the (!!) function you just pick the element you want. This has two advantages: Firstly the code is a straightforward translation of the mathematical definition of the algorithm. Secondly and more importantly you have a separation of concerns here: You have the infinite list. Independent of that you have the function to pick an element from it. Independent of both you have an IO computation to display the result. This makes your code very composable. With this solution you have also used a second design pattern, which you won't find in the mainstream languages: corecursion. At some point you will learn to use these tools and design patterns more consciously. This is your road to mastering Haskell. Greets, Ertugrul -- nightmare = unsafePerformIO (getWrongWife >>= sex) http://ertes.de/
participants (7)
-
Amy de Buitléir
-
Christopher Done
-
Costello, Roger L.
-
Ertugrul Soeylemez
-
Henning Diedrich
-
Iñaki Garay
-
KC