修复的固定点:: Eq a =>(a-> a)-> a-> a

时间:2018-12-02 18:51:28

标签: haskell

大家好,我正在尝试实现高阶函数修复,该修复从初始点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

注意:您的 如果函数从开始不收敛,函数将不会终止 点。 有谁可以帮助我吗 ?我尝试过,但没有返回任何内容

3 个答案:

答案 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),否则返回fx2的固定点,因此前进了一步。 “ 寻找固定点”。

答案 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