在Haskell中用(广义)箭头写因子

时间:2014-05-22 13:03:14

标签: haskell typeclass arrows

我想在Haskell的(->)箭头中写一个阶乘。我不知道如何将递归转换为loop。我已经设法使用loop为我的阶乘做了一个修复点,但现在有一个lambda-abstraction的问题,我无法翻译。

loop f b = let (d, c) = f (d, b) in c
g = \(f, x) -> (\x -> if x == 0 then 1 else x * f (x - 1), f x)
main = print $ loop g 5

在另一个箭头中编写阶乘的article转换了流:[a] -> [b],但我并不感兴趣。我正在寻找的更多like that

如何在(->)箭头中编写因子?

2 个答案:

答案 0 :(得分:1)

这是Haskell箭头符号中的阶乘函数的等效递归定义。

fact :: Integer -> Integer
fact = proc b -> do
    rec
        c <- f -<< b
        f <- g -< f
    returnA -< c

g :: (Integer -> Integer) -> Integer -> Integer
g f x = if x == 0 then 1 else x * f (x-1)

递归块的第二行表明了阶乘函数是g的固定点这一事实。在第一行中,需要更高阶的箭头应用-<<,因为f也是块内的箭头。该行也可以写成

c <- app -< (f,b)

通过仅定义数据,即没有高阶箭头应用,是否可以在递归箭头符号中定义是不可能的。

答案 1 :(得分:1)

一种可能性是首先将递归转换为使用fix,然后使用fix实现loop

import Control.Arrow

fix :: (a -> a) -> a
fix = loop (\(f, x) -> let x' = f x in (x', x'))

使用箭头符号表示无点:

fix = loop (uncurry ($) >>> (id &&& id))