# Common Misunderstandings

### From HaskellWiki

DekuDekuplex (Talk | contribs) (Corrected bug in second entry under "Guards" section submitted by user 7stud, and, per 7stud's request, removed double-quotes around the username thereof.) |
(→If / Then / Else) |
||

(3 intermediate revisions by 3 users not shown) | |||

Line 26: | Line 26: | ||

</code> | </code> | ||

− | The above is valid | + | The above is valid C code, a [http://en.wikipedia.org/wiki/Ternary_operation ternary operation], that's used quite commonly as a shortcut to typing out a full if-then-else block. It states that if <code>b</code> is true then <code>x = y</code> otherwise <code>x = z</code>. Notice how this makes no sense without <code>z</code>. Similarly, in Haskell an <hask>if</hask>/<hask>then</hask> makes no sense without an <hask>else</hask>. |

<haskell> | <haskell> | ||

Line 55: | Line 55: | ||

</haskell> | </haskell> | ||

+ | == Binding of Type Signatures == | ||

+ | Due to the typeclass overloading of numbers, lists of numbers are often typed as: | ||

+ | |||

+ | <haskell> | ||

+ | ghci> [1,2,3,4] :: [Float] | ||

+ | </haskell> | ||

+ | |||

+ | This works fine when the list stands alone, but when applying a function take note the function application binds stronger than the type signature. This means the below signature is invalid: | ||

+ | |||

+ | <haskell> | ||

+ | ghci> map floor [1,2,3,4] :: [Float] | ||

+ | </haskell> | ||

+ | |||

+ | and should instead be: | ||

+ | <haskell> | ||

+ | ghci> map floor ([1,2,3,4] :: [Float]) | ||

+ | </haskell> | ||

== '''do''' Notation == | == '''do''' Notation == |

## Revision as of 21:37, 24 August 2011

## Contents |

# 1 Common Mistakes and Incorrect Beliefs By Haskell Beginners

People going from zero to Haskell are likely to 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 Binding of Type Signatures

Due to the typeclass overloading of numbers, lists of numbers are often typed as:

ghci> [1,2,3,4] :: [Float]

This works fine when the list stands alone, but when applying a function take note the function application binds stronger than the type signature. This means the below signature is invalid:

ghci> map floor [1,2,3,4] :: [Float]

and should instead be:

ghci> map floor ([1,2,3,4] :: [Float])

## 1.4 **do** Notation

If the do notation page ever exists I'll advise 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.5 Iterating Over a List

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

in the following program:

hanoi :: a -> a -> a -> Int -> [(a, a)] hanoi source using dest n | 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 [(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 '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.

## 1.6 Guards

(The following two tips on guards were contributed by the user 7stud in the thread "Top beginner mistakes" (see http://article.gmane.org/gmane.comp.lang.haskell.beginners/1121) on the Haskell-Beginners mailing list on Wed, 4 Mar 2009 21:54:05 +0000 (UTC).)

Some beginners make the mistake of putting an equals sign after a function name when using guards; *viz.*:

myfunction x y = | x < 2 = "a" | y > 20 = "b" | otherwise = "c"

This causes a cryptic error message similar to the following to be displayed:

Failed, modules loaded: none.

Another common mistake that some beginners make is writing "if" in front of the guard conditions; *viz.*:

myfunction x y | if x < 2 = "a" | if y > 20 = "b" | otherwise = "c"

This causes a mysterious error message similar to the following to be shown:

Failed, modules loaded: none.

In both cases, the error messages don't help to identify the problem.

(Entry added by Benjamin L. Russell.)

## 1.7 Parentheses

(The following tip on parentheses was contributed by the user 7stud in the thread "Top beginner mistakes" (see http://article.gmane.org/gmane.comp.lang.haskell.beginners/1121) on the Haskell-Beginners mailing list on Wed, 4 Mar 2009 21:54:05 +0000 (UTC).)

Some beginners make the mistake of not putting parentheses around arguments of the form x:xs; *viz.*:

dosomething x:xs = head xs

This causes an ambiguous error message similar to the following to be shown:

Failed, modules loaded: none.

Here, the error message doesn't help to recognize the problem.

(Entry added by Benjamin L. Russell.)