52700.fb2
Также импортируем для удобства символьный синоним для fmap из модуля Control.Applicative.
Ленивее некуда | 189
import Control.Applicative((<$> ))
...
Проверим функцию int. Для этого сохраним все новые функции в модуле Stream. hs. Загрузим модуль
в интерпретатор и вычислим производную какой-нибудь функции. Найдём решение для правой части кон-
станты и проверим, что у нас получилась тождественная функция:
*Stream> dist 1000 time $ int 0 $ repeat 1
7.37188088351104e-17
Функции практически совпадают, порядок ошибки составляет 10 − 16. Так и должно быть для линейных
функций. Посмотрим, что будет если в правой части уравнения стоит тождественная функция:
*Stream> dist 1000 ((\t -> t^2/2) <$> time) $ int 0 time
2.497500000001403e-4
Решение этого уравнения равно функции t 2 . Здесь мы видим, что результаты уже не такие хорошие.
2
Есть функции, которые определяются рекурсивно в терминах дифференциальных уравнений, например
экспонента будет решением такого уравнения:
dx = x
dt
∫ t
x( t) = x(0) +
x( τ ) dτ
0
Опишем это уравнение в Haskell:
e = int 1 e
Наше описание копирует исходное математическое определение. Добавим это уравнение в модуль Stream
и проверим результаты:
*Stream> dist 1000 (map exp time) e
^CInterrupted.
К сожалению вычисление зависло. Нажмём ctrl+c и разберёмся почему. Для этого распишем вычисление
потока чисел e:
e
-- раскроем e
=>
int 1 e
-- раскроем int, во втором варгументе
-- int стоит декомпозиция,
=>
int 1 e@(f:fs)
-- для того чтобы узнать какое уравнение
-- для int выбрать нам нужно раскрыть
-- второй аргумент, узнать корневой
-- конструктор, раскроем второй аргумент:
=>
int 1 (int 1 e)
=>
int 1 (int 1e@(f:fs))
-- такая же ситуация
=>