Ответ 1
Этот бит волшебства работает из-за хэскелов лень. Как вы, возможно, знаете, Haskell оценивает значение при необходимости, а не когда определено. Таким образом, это работает, если вам не нужно вводить значение напрямую или позже.
rec
реализуется с использованием функции loop
ArrowLoop
. Он определяется следующим образом:
class Arrow a => ArrowLoop a where
loop :: a (b,d) (c,d) -> a b c
instance ArrowLoop (->) where
loop f b = let (c,d) = f (b,d) in c
Вы можете видеть: выход только что подан как вход. Он будет рассчитан только один раз, потому что Haskell будет оценивать только d
, когда это необходимо.
Здесь приведен пример использования комбинатора loop
. Эта функция вычисляет все аргументы аргумента:
powers = loop $ \(x,l) -> (l,x:map(*x)l)
(Вместо этого вы можете записать его следующим образом: powers x = fix $ (x :) . map (*x)
)
Как это работает? Ну, бесконечный список полномочий находится в аргументе l
. Оценка выглядит следующим образом:
powers = loop $ \(x,l) -> (l,x:map(*x)l) ==>
powers b = let (c,d) = (\(x,l) -> (l,x:map(*x)l)) (b,d) in c ==>
powers b = let (c,d) = (d,b:map(*b)d) in d ==> -- Now we apply 2 as an argument
powers 2 = let (c,d) = (d,2:map(*2)d) in d ==>
= let (c,(2:d)) = (d,2:map(*2)d) in c ==>
= let (c,(2:4:d)) = ((2:d),2:map(*2)(2:d)) in c ==>
= let (c,(2:4:8:d)) = ((2:4:d),2:map(*2)(2:4:d)) in ==> -- and so on