# Common Misunderstandings

### From HaskellWiki

DekuDekuplex (Talk | contribs) |
|||

Line 58: | Line 58: | ||

Sorry this isn't the full picture - for an inverse point of view see [[do notation considered harmful]]. | Sorry this isn't the full picture - for an inverse point of view see [[do notation considered harmful]]. | ||

+ | |||

+ | == Iterating Over a List == | ||

+ | Some beginners make the mistake of mistaking a single-element list pattern (such as <hask>[x]</hask>) for a pattern that iterates over every element in the list. | ||

+ | |||

+ | One example that recently (in April, 2008) appeared on the Haskell-Cafe mailing list was the following. Here, one coder attempted to write a function <hask>hanoi</hask> to solve the Towers of Hanoi problem, but to code it so that each tower could be named polymorphically. The problematic code segment was the following: | ||

+ | |||

+ | <haskell> | ||

+ | hanoi_shower [(a, b)] = "Move " ++ show a ++ " to " ++ | ||

+ | show b ++ "." | ||

+ | </haskell> | ||

+ | |||

+ | in the following program: | ||

+ | |||

+ | <haskell> | ||

+ | hanoi :: a -> a -> a -> Int -> [(a, a)] | ||

+ | hanoi a b c n = hanoi_helper a b c n | ||

+ | |||

+ | hanoi_helper :: a -> a -> a -> Int -> [(a, a)] | ||

+ | hanoi_helper source using dest n | ||

+ | | n == 1 = [(source, dest)] | ||

+ | | otherwise = hanoi_helper source dest using (n-1) | ||

+ | |||

+ | ++ hanoi_helper source using dest 1 | ||

+ | ++ hanoi_helper using source | ||

+ | dest (n-1) | ||

+ | |||

+ | hanoi_shower :: Show a => [(a, a)] -> String | ||

+ | hanoi_shower [(a, b)] = "Move " ++ show a ++ " to " ++ | ||

+ | show b ++ "." | ||

+ | </haskell> | ||

+ | |||

+ | The coder tried to run the code in WinHugs as follows: | ||

+ | |||

+ | <hask> | ||

+ | Main> putStr (hanoi_shower (hanoi 'a' 'b' 'c' 2)) | ||

+ | </hask> | ||

+ | |||

+ | However, this was the result: | ||

+ | |||

+ | <hask> | ||

+ | Program error: pattern match failure: hanoi_shower | ||

+ | [('a','b'),('a','c')] ++ ([] ++ hanoi_helper 'b' 'a' | ||

+ | 'c' (2 - 1)) | ||

+ | </hask> | ||

+ | |||

+ | The problem was that the parameter <hask>[(a, b)]</hask> to <hask>hanoi_shower</hask> only matched the first element of the list, but didn't iterate over the list as intended. | ||

+ | |||

+ | Here is a corrected version of the code above: | ||

+ | |||

+ | <haskell> | ||

+ | hanoi_shower :: Show a => [(a, a)] -> String | ||

+ | hanoi_shower moves = unlines ["Move " ++ show a ++ " to "++ show b ++ "." | (a, b) <- moves] | ||

+ | </haskell> | ||

+ | |||

+ | Here, <hask>moves</hask> is pattern-matched to type <hask>[(a, a)]</hask> (a list of pairs). The problem is how to iterate over the elements (pairs) of the list while separating the first <hask>a</hask> of each pair from the second <hask>a</hask>. | ||

+ | |||

+ | The solution above uses list comprehension: the generator <hask>(a, b) <- moves</hask> feeds each pair in turn to the left-hand expression <hask>(a, b)</hask>, and this pair is mapped to the left expression, <hask>"Move " ++ show a ++ " to "++ show b ++ "."</hask>, building a new list of sentences representing moves. Then, the function <hask>unlines</hask> breaks this list into a sequence of lines. | ||

+ | |||

+ | Here is the result of executing the above code in WinHugs: | ||

+ | |||

+ | <hask> | ||

+ | Main> putStr (hanoi_shower (hanoi 'a' 'b' 'c' 2)) | ||

+ | Move 'a' to 'b'. | ||

+ | Move 'a' to 'c'. | ||

+ | Move 'b' to 'c'. | ||

+ | |||

+ | Main> putStr (hanoi_shower (hanoi 1 2 3 2)) | ||

+ | Move 1 to 2. | ||

+ | Move 1 to 3. | ||

+ | Move 2 to 3. | ||

+ | </hask> | ||

+ | |||

+ | Notice that since <hask>a</hask> and <hask>b</hask> in <hask>(a, b)</hask> are polymorphic types, they can range over both <hask>Chars</hask> and <hask>Ints</hask>. | ||

+ | |||

+ | Another way of writing <hask>hanoi_shower</hask>, using <hask>map</hask>, is as follows: | ||

+ | |||

+ | <haskell> | ||

+ | hanoi_shower :: Show a => [(a, a)] -> String | ||

+ | hanoi_shower moves = unlines (map move moves) | ||

+ | where move (a, b) = "Move " ++ show a ++ " to "++ show b ++ "." | ||

+ | </haskell> | ||

+ | |||

+ | Here, <hask>move</hask> is mapped over <hask>moves</hask>, and each pair <hask>(a, b)</hask> of <hask>moves</hask> is pattern-matched against <hask>"Move " ++ show a ++ " to "++ show b ++ "."</hask> | ||

+ | |||

+ | Another way to map over a list is to use recursion, although this method is considered non-idiomatic Haskell (Haskellers generally prefer using higher-order functions over recursion when possible): | ||

+ | |||

+ | <haskell> | ||

+ | hanoi :: a -> a -> a -> Int -> [(a, a)] | ||

+ | hanoi source using dest n | ||

+ | | n == 0 = [] | ||

+ | | n == 1 = [(source, dest)] | ||

+ | | otherwise = hanoi source dest using (n-1) | ||

+ | ++ hanoi source using dest 1 | ||

+ | ++ hanoi using source dest (n-1) | ||

+ | |||

+ | hanoi_shower :: Show a => [(a, a)] -> String | ||

+ | hanoi_shower [] = "" | ||

+ | hanoi_shower ((a, b):moves) = unlines ["Move " ++ show a ++ " to "++ show b ++ "."] ++ hanoi_shower moves | ||

+ | </haskell> | ||

+ | |||

+ | Here, in <hask>hanoi_shower</hask>, the base case is simply an empty list <hask>[]</hask>. At each recursive step, a list of type <hask>[(a, a)]</hask> (a list of pairs) is mapped against the parameter <hask>(a, b):moves</hask> of <hask>hanoi_shower</hask>. This separates the head of the list <hask>(a, b)</hask> from the tail of the list <hask>moves</hask>, which then is further matched against <hask>((a, b):moves)</hask> on the next recursive call. | ||

+ | |||

+ | There are other ways of iterating over lists as well. One advantage of Haskell is that there are often many ways of performing the same action, including iterating over lists. |

## Revision as of 03:34, 17 April 2008

## Contents |

# 1 Common Mistakes and Incorrect Beliefs By Haskell Beginners

People going from zero to Haskell are likely gain a misunderstanding or miss a point that isn't stressed enough. Here are some mistakes that have been observed from multiple sources.

## 1.1 Indentation

Perhaps the first trip-up - you might understand that indentation defines where a code block starts and the lack of an equal amount of indentation indicates the previous code block ended. What some miss is thatif boolean then expr1 else expr2

Or they can be on the same line as the if:

if boolean then expr1 else expr2

## 1.2 If / Then / Else

if-then statements must always include an 'else' portion. It might be best not to think of if-then-else as flow control, as in most imperative languages, but think of it as construction of a value using a well formed expression.

```
x = b ? y : z;
```

`b`

is true then `x = y`

otherwise `x = z`

. Notice how this makes no sense without `z`

. Similarly, in Haskell an let x = if b then y -- compare to x = b ? y

`x`

when `b`

is false? One should also recognize that the types returned by the main = do startNetwork <- askUser "Network? " if startNetwork then do iface <- initNetworkInterface handlePackets iface else return ()

main = do startNetwork <- askUser "Network? " when startNetwork (do iface <- initNetworkInterface handlePackets iface )

## 1.3 **do** Notation

If the do notation page ever exists I'll advice you to check it out. Until then, understand that a missing Sorry this isn't the full picture - for an inverse point of view see do notation considered harmful.

## 1.4 Iterating Over a List

Some beginners make the mistake of mistaking a single-element list pattern (such ashanoi_shower [(a, b)] = "Move " ++ show a ++ " to " ++ show b ++ "."

in the following program:

hanoi :: a -> a -> a -> Int -> [(a, a)] hanoi a b c n = hanoi_helper a b c n hanoi_helper :: a -> a -> a -> Int -> [(a, a)] hanoi_helper source using dest n | n == 1 = [(source, dest)] | otherwise = hanoi_helper source dest using (n-1) ++ hanoi_helper source using dest 1 ++ hanoi_helper using source dest (n-1) hanoi_shower :: Show a => [(a, a)] -> String hanoi_shower [(a, b)] = "Move " ++ show a ++ " to " ++ show b ++ "."

The coder tried to run the code in WinHugs as follows:

However, this was the result:

[('a','b'),('a','c')] ++ ([] ++ hanoi_helper 'b' 'a'

'c' (2 - 1))

Here is a corrected version of the code above:

hanoi_shower :: Show a => [(a, a)] -> String hanoi_shower moves = unlines ["Move " ++ show a ++ " to "++ show b ++ "." | (a, b) <- moves]

Here is the result of executing the above code in WinHugs:

Move 'a' to 'b'.

Move 'a' to 'c'.

Move 'b' to 'c'.

Main> putStr (hanoi_shower (hanoi 1 2 3 2))

Move 1 to 2.

Move 1 to 3.

Move 2 to 3.

hanoi_shower :: Show a => [(a, a)] -> String hanoi_shower moves = unlines (map move moves) where move (a, b) = "Move " ++ show a ++ " to "++ show b ++ "."

Another way to map over a list is to use recursion, although this method is considered non-idiomatic Haskell (Haskellers generally prefer using higher-order functions over recursion when possible):

hanoi :: a -> a -> a -> Int -> [(a, a)] hanoi source using dest n | n == 0 = [] | n == 1 = [(source, dest)] | otherwise = hanoi source dest using (n-1) ++ hanoi source using dest 1 ++ hanoi using source dest (n-1) hanoi_shower :: Show a => [(a, a)] -> String hanoi_shower [] = "" hanoi_shower ((a, b):moves) = unlines ["Move " ++ show a ++ " to "++ show b ++ "."] ++ hanoi_shower moves

There are other ways of iterating over lists as well. One advantage of Haskell is that there are often many ways of performing the same action, including iterating over lists.