Упражнения по программированию на 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 λ:
- Проработайте примеры из этой главы, используя 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)