Programming in Haskell exercises (2)
Working on exercises of Chapter 2 First steps
Change terminal prompt and ghci prompt. Let ghci support multiple lines.
% export PS1="👍 "
👍 cat ~/.ghci
:set prompt "λ: "
:set +m
:set prompt-cont " | "
👍 ghci
GHCi, version 8.2.1: http://www.haskell.org/ghc/ :? for help
Loaded GHCi configuration from /Users/zhijunsheng/.ghci
λ:
- Work through the examples from this chapter using GHCi.
λ: 2+3*4
14
λ: (2+3)*4
20
λ: sqrt (3^2 + 4^2)
5.0
λ:
Function head, tail, take, length, sum, product and reverse:
λ: head [1,2,3,4,5]
1
λ: tail [1,2,3,4,5]
[2,3,4,5]
λ: [1,2,3,4,5] !! 2
3
λ: take 3 [1,2,3,4,5]
[1,2,3]
λ: drop 3 [1,2,3,4,5]
[4,5]
λ: length [1,2,3,4,5]
5
λ: sum [1,2,3,4,5]
15
λ: product [1,2,3,4,5]
120
λ: [1,2,3] ++ [4,5]
[1,2,3,4,5]
λ: reverse [1,2,3,4,5]
[5,4,3,2,1]
Haskell source code in file test.hs:
👍 vim test.hs
👍 ghci test.hs
GHCi, version 8.2.1: http://www.haskell.org/ghc/ :? for help
Loaded GHCi configuration from /Users/zhijunsheng/.ghci
[1 of 1] Compiling Main ( test.hs, interpreted )
Ok, 1 module loaded.
λ: quadruple 10
40
λ: take (double 2) [1,2,3,4,5]
[1,2,3,4]
Edit test.hs in another terminal. Update code and save with vim command :w.
double x = x + xquadruple x = double (double x)factorial n = product [1..n]average ns = sum ns `div` length ns~
~
~
~
"test.hs" 8L, 118C written
Reload test.hs using ghci command :reload or :r.
λ: :reload
[1 of 1] Compiling Main ( test.hs, interpreted )
Ok, 1 module loaded.
λ: factorial 10
3628800
λ: average [1,2,3,4,5]
3
test.hs with indentation sample:
double x = x + xquadruple x = double (double x)factorial n = product [1..n]average ns = sum ns `div` length nsa = b + c
where
b = 1
c = 2
d = a * 2
Reload and try:
λ: :reload
[1 of 1] Compiling Main ( test.hs, interpreted )
Ok, 1 module loaded.
λ: a
3
λ: d
6
Use curly braces:
a = b + c
where
{ b = 1;
c = 2 };
d = a * 2
Reload and try:
λ: :r
[1 of 1] Compiling Main ( test.hs, interpreted )
Ok, 1 module loaded.
λ: a
3
λ: d
6
Put everything on a single line:
a = b + c where { b = 1; c = 2 }; d = a * 2
Reload and try:
λ: :r
[1 of 1] Compiling Main ( test.hs, interpreted )
Ok, 1 module loaded.
λ: a
3
λ: d
6
Single line comment and block comment:
{-
double x = x + xquadruple x = double (double x)
-}-- Factorial of a positive integer:
factorial n = product [1..n]-- Average of a list of integers:
average ns = sum ns `div` length nsa = b + c where { b = 1; c = 2 }; d = a * 2
Function double was commented out:
λ: :r
[1 of 1] Compiling Main ( test.hs, interpreted )
Ok, 1 module loaded.
λ: double 3<interactive>:16:1: error:
Variable not in scope: double :: Integer -> t
λ: a
3
2. Parenthesize the following numeric expressions:
2 ^ 3 * 4
2 * 3 + 4 * 5
2 + 3 * 4 ^ 5
λ: 2^3*4
32
λ: (2^3)*4
32
λ: 2*3+4*5
26
λ: (2*3)+(4*5)
26
λ: 2+3*4^5
3074
λ: 2+(3*(4^5))
3074
3. The script below contains three syntactic errors. Correct these errors and then check that your script works properly using GHCi.
N = a ‘div’ length xs
N = a 'div' length xs
where
a = 10
xs = [1,2,3,4,5]
N should be n
‘ should be `
xs should be aligned with a of the previous line
λ: let
| N = a 'div' length xs
| where
| a = 10
| xs = [1,2,3,4,5]
|<interactive>:27:1: error:
parse error (possibly incorrect indentation or mismatched brackets)
λ:
3 errors corrected:
λ: let
| n = a `div` length xs
| where
| a = 10
| xs = [1,2,3,4,5]
|
λ: n
2
4. The library function last
selects the last element of a non-empty list; for example last [1,2,3,4,5] = 5
. Show how the function last
could be defined in terms of the other library function introduced in this chapter. Can you think of another possible definition?
λ: let
| last' :: [a] -> a
| last' xs = head $ reverse xs
|
λ: last' [1..20]
20
Here is a different way using index:
λ: let
| last' :: [a] -> a
| last' xs = xs !! (length xs - 1)
|
λ: last' [1..20]
20
5. The library function init
removes the last element from a non-empty list; for example, init [1,2,3,4,5] = [1,2,3,4]
. Show how init could similarly be defined in two different ways.
λ: let
| init' :: [a] -> [a]
| init' xs = take (length xs - 1) xs
|
λ: init' [1..20]
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]
Here is a different way using reverse and tail:
λ: let
| init' :: [a] -> [a]
| init' xs = reverse $ tail $ reverse xs
|
λ: init' [1..20]
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]