52700.fb2 Учебник по Haskell - читать онлайн бесплатно полную версию книги . Страница 211

Учебник по Haskell - читать онлайн бесплатно полную версию книги . Страница 211

where (x:xs) = a

lazyHead a =

let (x:xs) = a

in

x

Посмотрим как используются ленивые образцы при построении потоков, или бесконечных списков. Мы

будем представлять функции одного аргумента потоками значений с одинаковым шагом. Так мы будем пред-

ставлять непрерывные функции дискретными сигналами. Считаем, что шаг дискретизации (или шаг между

соседними точками) нам известен.

f : R → R ⇒ fn = f ( ) ,

n = 0 , 1 , 2 , ...

Где τ – шаг дискретизации, а n пробегает все натуральные числа. Определим функцию решения диффе-

ренциальных уравнений вида:

dx = f( t)

dt

x(0) = ˆ

x

Символ ˆ x означает начальное значение функции x. Перейдём к дискретным сигналам:

xn−xn− 1 = f

τ

n,

x 0 = ˆ

x

Где τ – шаг дискретизации, а x и f – это потоки чисел, индекс n пробегает от нуля до бесконечности

по всем точкам функции, превращённой в дискретный сигнал. Такой метод приближения дифференциаль-

ных уравнений называют методом Эйлера. Теперь мы можем выразить следующий элемент сигнала через

предыдущий.

xn = xn− 1 + τ fn, x 0 = ˆ

x

Закодируем это уравнение:

-- шаг дискретизации

dt :: Fractional a => a

dt = 1e-3

-- метод Эйлера

int :: Fractional a => a -> [a] -> [a]

int x0 (f:fs) = x0 : int (x0 + dt * f) fs

Смотрите в функции int мы принимаем начальное значение x0 и поток всех значений функции пра-

вой части уравнения, поток значений функции f( t). Мы помещаем начальное значение в первый элемент

результата, а остальные значения получаем рекурсивно.

Определим две вспомогательные функции:

time :: Fractional a => [a]

time = [0, dt .. ]

dist :: Fractional a => Int -> [a] -> [a] -> a

dist n a b = ( / fromIntegral n) $

foldl’ (+) 0 $ take n $ map abs $ zipWith (-) a b

Функция time пробегает все значения отсчётов шага дискретизации по времени. Это тождественная функ-

ция представленная в виде потока с шагом dt.

Функция проверки результата dist принимает два потока и по ним считает расстояние между ними. Эта

функция говорит, что расстояние между двумя потоками в n первых точках равно сумме модулей разности

между значениями потоков. Для того чтобы оценить среднее расхождение, мы делим в конце результат на