На этом шаге мы рассмотрим процесс моделирования таких вычислений.
В языке Haskell существует строгая функция seq, которая имеет следующую сигнатуру типа:
Prelude> :t seq seq :: a -> b -> b
Другими словами, функция seq определена следующим образом:
seq(⊥,b)=⊥; seq(a,b)=b, если a≠⊥.
Первый аргумент вычисляется, как обычно, лишь до слабой заголовочной нормальной формы (англ. "weak head normal form"); например, слабой заголовочной нормальной формой для [1..] является 1:_.
(а) Prelude> seq 1 sin 3 0.14112 => seq(1,sin(3))=0.14112 (б) Prelude> seq (sin 4) 5 5 :: Integer => seq(sin(4),5)=5 (в) Prelude> seq [1..] 5 5 :: Integer => seq([1..],5)=5 (г) Prelude> seq (length [1..]) 5 "CTRL+Break" => 1 не завершаются 0... (д) Prelude> seq (error "123") 5 Program execution error: 123 => seq(⊥,5)=⊥ (е) Prelude> seq 1 "3"++(error "2") "3 Program execution error: 2 => seq(1,⊥)=⊥ (ж) Prelude> seq ("0"++error "1") ("0"++error "2") "0 Program execution error: 2 => seq(⊥,⊥)=⊥
Ещё одним способом моделирования строгих вычислений в языке Haskell является использование операции строгой аппликации ($!), которая определяется так:
f $! x = x `seq` (f x)
Напомним, что операция нестрогой аппликации ($) определяется следующим образом:
f $ x = f x
На следующем шаге мы рассмотрим конструирование потенциально бесконечных списков с помощью корекурсии.