На этом шаге мы рассмотрим данный способ создания списков.
Определитель списка является "синтаксическим сахаром" и используется для моделирования математического понятия "множество", определяемого с помощью характеристической функции множества (характеристического предиката).
Напомним, что синтаксический сахар - это особенности языка, которые упрощают чтение и написание кода и дают возможность выразить одни и те же действия разными способами.
Синтаксис определителя списка таков (читается: "список элементов x, взятых из исходного списка xs"):
[x¦x <- xs]
Слово x <- xs называется генератором списка; генератор для каждого x должен быть определён однозначно.
Генерация элементов списка происходит в соответствии с предикатом:
<Имя_функции> = [x¦x <- xs, <Условное_выражение_1>, <Условное_выражение_2>, ... <Условное_выражение_n>]
Условия, составляющие предикат определителя списка, можно представить в отдельной функции:
<Имя_функции> = [x¦x <- xs, <Имя_функции-предиката>] where <Имя_функции-предиката> = <Условное_выражение>
Приведем ряд демонстрационных примеров.
-- Демонстрация функции, конструирующей список из -- отрицательных элементов числового списка xs ---------------------------------------------- negLst:: [Int] -> [Int] negLst xs = [x|x <- xs, x<0] ------------------------------------------------- -- Демонстрация функции, конструирующей список из -- чётных элементов числового списка xs --------------------------------------- evenLst:: [Int] -> [Int] evenLst xs = [x|x <- xs, x `mod` 2==0] -------------------------------------------------- -- Демонстрация функции, конструирующей список пар -- элементов исходных двух списков xs и ys, при -- этом первый элемент пары должен быть не меньше -- второго элемента ------------------------------------ para:: [Int] -> [Int] -> [(Int,Int)] para xs ys = [(x,y)| x <- xs, y <- ys, x>=y] ------------------------------------------------ -- Демонстрация функций, конструирующих конечные -- n-элементные списки: -- (1) натуральных чисел; -- (2) нечётных натуральных чисел; -- (3) квадратов натуральных чисел; -- (4) факториалов; -- (5) степеней числа 2 ------------------------ f1 n = [1..n] f2 n = [1,3..n] f3 n = map (^2) [1..n] ------------------------ f4 n = map (fact) [1..n] where fact 0 = 1 fact x = x*fact (x-1) ------------------------------- f5 n = map (2^) [1..n] ------------------------------ -- Неудачные тестовые примеры: ----------------------------------------- test1 = negLst [] == [] && negLst [-4] == [-4] && negLst [4] == [] && negLst [-1,2,-3] == [-1,-3] && negLst [1,2,3,4,5] == [] && negLst [-1,-2,-3,-4] == [-1,-2,-3,-4] && negLst [1,-2,3,-4,-5,6,7] == [-2,-4,-5] ------------------------------------------------- test2 = evenLst [] == [] && evenLst [1] == [] && evenLst [1,2] == [2] && evenLst [1,2,-3,-4,5,6] == [2,-4,6] && evenLst [10,22,314,411,523,61111] == [10,22,314] && evenLst [-11,314,411,-522,61111] == [314,-522] -------------------------------------------------------------- test3 = para [3] [-1,0,-3,5] == [(3,-1),(3,0),(3,-3)] && para [3,4,5] [6,78] == [] && para [1] [] == [] && para [] [2] == [] && para [2] [1] == [(2,1)] && para [-3,-4,5] [-6,-2,78,4] == [(-3,-6),(-4,-6), (5,-6),(5,-2),(5,4)] -------------------------------------------------------------- test4 = f1 5 == [1,2,3,4,5] && f2 5 == [1,3,5] && f3 5 == [1,4,9,16,25] && f4 5 == [1,2,6,24,120] && f5 5 == [2,4,8,16,32]
-- Демонстрация вычисления значения функции y=cos(x) -- с помощью разложения функции в ряд Тейлора в ок- -- рестности точки x=0 -- -- 2 4 6 2k -- x x x k x -- cos(x)=1- -- + -- - -- +...+(-1) ----- +... -- 2! 4! 6! (2k)! -- -- ********************************************* -- Результат вычисления значения функции cos(x); -- k - количество слагаемых ряда Тейлора ---------------------------------------- cos' x k = sum (abc x k) -- **************************************** -- Функция, возвращающая список, содержащий -- k слагаемых ряда Тейлора ----------------------------------- abc:: Double -> Integer -> [Double] abc x k = [a x n | n <- [0..k]] -- ***************************************** -- Функция, возвращающая значение n-го члена -- ряда Тейлора в точке x ------------------------------- a:: Double -> Integer -> Double a x n | n==0 = 1 | True = -x*x/((2*y-1)*2*y)*(a x (n-1)) where y = fromInteger n -- ****************************************** -- Функция, возвращающая "остаток" от деления -- вещественных чисел a и b ---------------------------------- perev:: Double -> Double -> Double perev a b = a-b*fromInt (truncate (a/b)) -- ************************************* -- Функция, реализующая тестирование -------------------------------------------- test :: Double -> Integer ->(Double, Double) test x k = (cos' (perev x (2*pi)) k, cos x) -------------------------------------------
-- Демонстрация вычисления значения функции y=sin(x) -- с помощью разложения функции в ряд Тейлора в ок- -- рестности точки x=0 -- -- 3 5 7 2k+1 -- x x x k x -- sin(x)=x- -- + -- - -- +...+(-1) ------- +... -- 3! 5! 7! (2k+1)! -- -- ********************************************* -- Результат вычисления значения функции sin(x); -- k - количество слагаемых ряда Тейлора ---------------------------------------- sin' x k = sum (abc x k) -- **************************************** -- Функция, возвращающая список, содержащий -- k слагаемых ряда Тейлора ----------------------------------- abc:: Double -> Integer -> [Double] abc x k = [a x n | n <- [0..k]] -- ***************************************** -- Функция, возвращающая значение n-го члена -- ряда Тейлора в точке x ------------------------------- a:: Double -> Integer -> Double a x k | k==0 = x | True = -x*x/((2*y+1)*2*y)*(a x (k-1)) where y = fromInteger k -- ****************************************** -- Функция, возвращающая "остаток" от деления -- вещественных чисел a и b ---------------------------------- perev:: Double -> Double -> Double perev a b = a-b*fromInt (truncate (a/b)) -- ************************************* -- Функция, реализующая тестирование -------------------------------------------- test :: Double -> Integer -> (Double,Double) test x k = (sin' (perev x (2*pi)) k, sin x)
[f x|x <- lst] = map f lst, [x|x <- lst, p x] = filter p lst, concat [[e|p]|Q] = [e|Q, p]
На следующем шаге мы приведем перечень задач для самостоятельного решения.