Упражнения по программированию на Haskell (2)

Работа над упражнениями главы 2 Первые шаги

Изменить подсказку терминала и подсказку ghci. Пусть ghci поддерживает несколько линий.

% 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
λ:
  1. Проработайте примеры из этой главы, используя GHCi.
λ: 2+3*4
14
λ: (2+3)*4
20
λ: sqrt (3^2 + 4^2)
5.0
λ:

Функции головы, хвоста, взятия, длины, суммы, произведения и реверса:

λ: 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 в файле 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]

Отредактируйте test.hs в другом терминале. Обновите код и сохраните с помощью команды vim: w.

double x = x + x
quadruple x = double (double x)
factorial n = product [1..n]
average ns = sum ns `div` length ns
~                                                   
~                                                   
~                                                   
~                                                   
"test.hs" 8L, 118C written

Перезагрузите test.hs с помощью команды ghci :reload или :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 с образцом отступа:

double x = x + x
quadruple x = double (double x)
factorial n = product [1..n]
average ns = sum ns `div` length ns
a = b + c
    where 
      b = 1
      c = 2
d = a * 2

Перезагрузите и попробуйте:

λ: :reload
[1 of 1] Compiling Main             ( test.hs, interpreted )
Ok, 1 module loaded.
λ: a
3
λ: d
6

Используйте фигурные скобки:

a = b + c
    where 
      { b = 1;
        c = 2 };
d = a * 2

Перезагрузите и попробуйте:

λ: :r
[1 of 1] Compiling Main             ( test.hs, interpreted )
Ok, 1 module loaded.
λ: a
3
λ: d
6

Поместите все в одну строку:

a = b + c where { b = 1; c = 2 }; d = a * 2

Перезагрузите и попробуйте:

λ: :r
[1 of 1] Compiling Main             ( test.hs, interpreted )
Ok, 1 module loaded.
λ: a
3
λ: d
6

Однострочный комментарий и блочный комментарий:

{-
double x = x + x
quadruple 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 ns
a = b + c where { b = 1; c = 2 }; d = a * 2

Функция double была закомментирована:

λ: :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. Заключите в скобки следующие числовые выражения:
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. Сценарий ниже содержит три синтаксические ошибки. Исправьте эти ошибки, а затем проверьте правильность работы вашего скрипта с помощью GHCi.
N = длина «div» xs

N = a 'div' length xs
    where
       a = 10
      xs = [1,2,3,4,5]

N должно быть n

"должно быть"

xs должен быть выровнен с предыдущей строкой

λ: 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 ошибки:

λ: let
 | n = a `div` length xs
 |     where
 |        a = 10
 |        xs = [1,2,3,4,5]
 | 
λ: n
2

4. Библиотечная функция last выбирает последний элемент непустого списка; например last [1,2,3,4,5] = 5. Покажите, как можно определить функцию last в терминах другой библиотечной функции, представленной в этой главе. Можете ли вы придумать другое возможное определение?

λ: let 
 | last' :: [a] -> a
 | last' xs = head $ reverse xs
 | 
λ: last' [1..20]
20

Вот другой способ использования индекса:

λ: let 
 | last' :: [a] -> a
 | last' xs = xs !! (length xs - 1)
 | 
λ: last' [1..20]
20

5. Библиотечная функция init удаляет последний элемент из непустого списка; например, init [1,2,3,4,5] = [1,2,3,4]. Покажите, как можно аналогичным образом определить init двумя разными способами.

λ: 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]

Вот другой способ использования реверса и хвоста:

λ: 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]

Программирование на Haskell упражнения (1)

Программирование на Haskell упражнения (2)

Программирование на Haskell упражнения (3)