我是Haskell的初学者,现在开始学习折叠,而不是在大学,第一年。
我现在面临的一个问题是使用until
函数定义Euclid的算法。
这是Euclid的递归定义(编辑:只是为了展示euclid如何工作,我试图在没有递归的情况下定义euclid。只是使用直到):
gcd a b = if b == 0 then a else gcd b (a `mod` b)
以下是我使用的内容:
gcd a b = until (==0) (mod a ) b
显然这没有任何意义,因为它总是会返回0
,因为这是我的停止点,而不是打印b == 0
时的值。我不知道如何获得a
的价值。
感谢任何帮助。 提前谢谢你们。
答案 0 :(得分:4)
现在
until :: (a -> Bool) -> (a -> a) -> a -> a
所以我们需要一个可以反复应用的函数,直到条件成立,但我们有两个数字a
和b
,那么我们怎么做呢?
解决方案是将两个数字合并为一个值(a,b)
,因此请以这种方式考虑gcd
:
uncurriedGCD (a,b) = if b == 0 then (a,a) else uncurriedGCD (b,a `mod` b)
现在你可以制作两个功能,next
& check
并将其与until
一起使用。
until
的助手:next (a,b) = (b,a `mod` b)
check (a,b) = b == 0
这意味着我们现在可以使用uncurriedGCD
编写until
。
例如:
ghci> until check next (6,4)
(2,0)
ghci> until check next (12,18)
(6,0)
所以我们可以定义:
gcd a b = c where (c,_) = until check next (a,b)
,并提供:
ghci> gcd 20 44
4
ghci> gcd 60 108
12
答案 1 :(得分:2)
欧几里德算法所说的是:对于(a, b)
,计算(b, mod a b)
直到(新的)b
等于零。这可以直接转换为使用until
的实现,如下所示:
myGcd a b = until (\(x, y) -> y == 0) (\(x, y) -> (y, x `mod` y)) (a, b)