このちょっとした魔法は、haskells の怠惰のために機能します。ご存知かもしれませんが、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