大家好,我正在尝试实现高阶函数修复,该修复从初始点f :: a -> a
计算任意函数x
的{{3}}。也就是说,对于给定的fᴷ(x)
和f
,形式为x
的不动点。
-- CONTRACT
fix :: Eq a => (a -> a) -> a -> a
-- DEFINITION [TODO: Implement fix]
fix f x = ?
我当前的尝试是:
fix f x | f x == x = x
| otherwise = fix f x
where x = f x
注意:您的 如果函数从开始不收敛,函数将不会终止 点。 有谁可以帮助我吗 ?我尝试过,但没有返回任何内容
答案 0 :(得分:7)
一个常见的误解是,在编写x = ...
时,您会在Haskell中分配一个值。在Haskell中, not 不分配值,声明一个值。
因此,这意味着您基本上是在x
子句中构造了一个变量where
,而该变量{em>不是在函数开头的x
喜欢:
fix :: Eq a => (a -> a) -> a -> a
fix f _ | f x == x = x
| otherwise = fix f x
where x = f x
您在这里由此定义了x
本身:x = f x
,这意味着Haskell打算对此进行评估,它将开始计算f(f(f(f(f(f(...))))))
,但不检查< em>不动点。
因此,解决方案是引入一个新变量,例如x2
,并这样使用:
fix :: Eq a => (a -> a) -> a -> a
fix f x | x == x2 = x
| otherwise = fix f x2
where x2 = f x
所以这里x2
是下一个x
。给定x == x2
,我们返回x
(或x2
),否则返回f
和x2
的固定点,因此前进了一步。 “ 寻找固定点”。
答案 1 :(得分:4)
为下一步的迭代取一个不同的名称,就像这样:
where x' = f x
(而不是where x = f x
)。现在,请检查其余的现有代码,对于每次出现x
的问题,请问自己:我的意思是x
是这里还是x'
?
答案 2 :(得分:4)
您已经有了从头开始写fix
的答案。如果您想使用一些标准的Haskell函数来尝试它,建议您查看函数until
。
until :: (a -> Bool) -> (a -> a) -> a -> a
请注意,until
的类型与您想要的类型非常相似。它只需要使用a -> Bool
形式的一个额外参数。表达式until p f x
从起始点f
开始迭代地应用x
,直到满足某些条件p
为止。而且您应该可以轻松地以
fix
fix = until p
用于某些功能p :: a -> Bool
。现在,您只需要实现此停止条件p
,即可检查您计算出的点y
是否为f
的固定点,即f y == y
。