在非函数类型上“修复”有用的实例化?

时间:2015-01-20 01:08:48

标签: haskell recursion combinators

每次我使用fix :: (a -> a) -> a时,它都是

类型
((a -> b) -> a -> b) -> a -> b
某些ab

。实际上是否有fix的应用程序,其类型参数未实例化为函数类型,而不是像fix (const 0)这样的简单事物?将签名保留为最一般的目的是什么?

3 个答案:

答案 0 :(得分:10)

我不知道你是否认为这个例子是微不足道的,但是你可以直接使用fix(不经过一个函数)来建立数据:

repeat :: a -> [a]
repeat x = fix (x:)

答案 1 :(得分:8)

有许多使用fix构建corecursive数据的示例。我不太了解一般理论,但似乎任何类似于流的数据类型,因为到目前为止,您总是可以输出一个更多的值,可以使用{{1}计算没有给它一个函数类型。

实施例

最简单的例子(在Cactus的答案中给出)是一个重复的值流,例如

fix

这满足等式

x = [1, 1, 1, 1, 1, 1, 1, 1, ...]

可以通过

制作
(1:) x = x

一个稍微复杂的例子是自然数

>> fix (1:)
[1,1,1,1,1,1,1,1,1,1,...]

满足等式

n = [0, 1, 2, 3, 4, 5, 6, ...]

可以通过

制作
0 : map (+1) n = n

如果我们查看>> fix ((0:) . map (+1)) [0,1,2,3,4,5,6,7,8,9,...] (n,f)f阶乘数 -

,我们可以最轻松地生成阶乘数
n
如果我们将x = [(0,1), (1,1), (2,2), (3,6), (4,24), (5,120), ...] (n,f)带到(n+1, f*(n+1)),然后将(0,1)放到列表的开头,那么

是固定的。所以它们可以由

生成
>> fix $ \xs -> (0,1) : map (\(n,f) -> (n+1,f*(n+1))) xs
[(0,1),(1,1),(2,2),(3,6),(4,24),(5,120),(6,720),(7,5040),...]

可以类似地生成斐波纳契数,如user3237465的答案。

概括示例

这里的所有三个示例基本上都是递归函数转换为corecursive流,即它们具有一些初始状态s,并且流发出的值为sf s,{{1某些函数f (f s)等等。执行此操作的一般方法是函数f

iterate

可以用iterate :: (a -> a) -> a -> [a] iterate f x = x : iterate f (f x) -

来定义
fix

因此,任何重复将函数应用于某个状态的流都可以用iterate f x = x : map f (iterate f x) = (x:) . (map f) $ iterate f x = fix ((x:) . map f) 来编写(当然,您可以简单地使用fix代替iterate - a在允许递归let表达式的语言中fix不是必需的规则的特殊情况。)

非流式示例

对于不是流的示例,请考虑在分支处具有值的二叉树 -

fix

如果我们想要一个二叉树,其节点以广度优先顺序标记,请注意我们可以通过获取自身的两个副本来修复这样的树,并通过适当的方式递增左右分支中的所有值。金额,由以下函数定义 -

data Tree a = Tip | Bin a (Tree a) (Tree a) deriving (Show)

使用简单函数fun :: (Num a) => Tree a -> Tree a fun t = Bin 1 (incr 1 t) (incr 2 t) where incr n (Bin a l r) = Bin (a+n) (incr m l) (incr m r) where m = 2 * n 仅显示树的初始部分,然后我们将固定点计算为

takeLevels

这就是我们想要的。

答案 2 :(得分:5)

Fibonacci序列,例如:

fibs = fix ((1:) . (1:) . (zipWith (+) <*> tail))

forever功能:

forever x = fix (x >>)

斐波纳契序列的另一种变体:

fibs :: State (Int, Int) [Int]
fibs = fix $ \loop -> do
    (x, y) <- get
    put (y, y + x)
    (x :) <$> loop

main = print $ take 15 $ fst $ runState fibs (1, 1)

打印[1,1,2,3,5,8,13,21,34,55,89,144,233,377,610]