Haskell 检查函数是否两次返回相同的值
Haskell check if function returned same value twice
我正在做一个项目,遇到了一个有趣的问题。我有一个函数,我们称它为 foo
该函数将给定数字除以可能的最高除数,而不是除以 iteself。如果最高分频器是 1 那么它 returns 给定的数字。例如,数字 21 首先除以 7,然后 returns 3 + 它一直返回 3,因为除了 3 和 1 之外没有其他除法器。
ghci> foo 21
3
foo it
3
现在我想把这些步骤保存到函数中,即returns数组中的所有步骤。当前的实现是:
bar:: int-> [int]
bar x = x : bar (foo x)
此方法的问题在于它一直返回相同的值并且永不结束。有没有办法检查 foo 的前一次迭代是否返回相同的数字并停止,这样它就不会导致无限列表?
类似于:
bar 21
[3]
instead of:
bar 21
[3,3,3,3,3,3,3,3,3...]
在 oop 中,我会将最后一个值保存到 var 中,然后进行比较,但在 haskell 中并非如此,我不确定它还能如何实现
你应该检查x
是否等于foo x
,如果是这样,我们就可以停止递归,所以:
bar :: Int -> [Int]
bar x
| <strong>x == x'</strong> = [x]
| otherwise = x : bar x'
where x' = foo x
你这里也return先给定值。如果列表中的第一项应该是除以最大除数的数字,您可以使用:
bar :: Int -> [Int]
bar = go . foo
where go x
| <strong>x == x'</strong> = [x]
| otherwise = x : go x'
where x' = foo x
如果首选库样式,还可以涉及 unfoldr
库函数。
通用代码如下:
λ>
λ> :type unfoldr
unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
λ>
λ> stepFn f v = if (v == f v) then Nothing else Just (let fv = f v in (fv, fv))
λ> bar f v0 = v0 : L.unfoldr (stepFn f) v0
λ>
作为小白鼠,我们可以选择一个函数来迭代求整数平方根,比如 709。请注意,如果不进行一些额外的调整,它并不适用于所有数字,这只会模糊我们在这里的目的。
λ>
λ> foo n = div (n + div 709 n) 2
λ>
λ> foo 1
355
λ>
λ> foo 355
178
λ>
λ> foo 26
26
λ>
所以让我们尝试 bar
:
λ>
λ> :type bar
bar :: Eq b => (b -> b) -> b -> [b]
λ>
λ> bar foo 1
[1,355,178,90,48,31,26]
λ>
我正在做一个项目,遇到了一个有趣的问题。我有一个函数,我们称它为 foo
该函数将给定数字除以可能的最高除数,而不是除以 iteself。如果最高分频器是 1 那么它 returns 给定的数字。例如,数字 21 首先除以 7,然后 returns 3 + 它一直返回 3,因为除了 3 和 1 之外没有其他除法器。
ghci> foo 21
3
foo it
3
现在我想把这些步骤保存到函数中,即returns数组中的所有步骤。当前的实现是:
bar:: int-> [int]
bar x = x : bar (foo x)
此方法的问题在于它一直返回相同的值并且永不结束。有没有办法检查 foo 的前一次迭代是否返回相同的数字并停止,这样它就不会导致无限列表?
类似于:
bar 21
[3]
instead of:
bar 21
[3,3,3,3,3,3,3,3,3...]
在 oop 中,我会将最后一个值保存到 var 中,然后进行比较,但在 haskell 中并非如此,我不确定它还能如何实现
你应该检查x
是否等于foo x
,如果是这样,我们就可以停止递归,所以:
bar :: Int -> [Int]
bar x
| <strong>x == x'</strong> = [x]
| otherwise = x : bar x'
where x' = foo x
你这里也return先给定值。如果列表中的第一项应该是除以最大除数的数字,您可以使用:
bar :: Int -> [Int]
bar = go . foo
where go x
| <strong>x == x'</strong> = [x]
| otherwise = x : go x'
where x' = foo x
如果首选库样式,还可以涉及 unfoldr
库函数。
通用代码如下:
λ>
λ> :type unfoldr
unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
λ>
λ> stepFn f v = if (v == f v) then Nothing else Just (let fv = f v in (fv, fv))
λ> bar f v0 = v0 : L.unfoldr (stepFn f) v0
λ>
作为小白鼠,我们可以选择一个函数来迭代求整数平方根,比如 709。请注意,如果不进行一些额外的调整,它并不适用于所有数字,这只会模糊我们在这里的目的。
λ>
λ> foo n = div (n + div 709 n) 2
λ>
λ> foo 1
355
λ>
λ> foo 355
178
λ>
λ> foo 26
26
λ>
所以让我们尝试 bar
:
λ>
λ> :type bar
bar :: Eq b => (b -> b) -> b -> [b]
λ>
λ> bar foo 1
[1,355,178,90,48,31,26]
λ>