我在Haskell中实现此功能时遇到一些麻烦。以下是我到目前为止的情况:
--Extend coprime to a function on lists:
--coprime_with n list = True exactly when n is coprime with
--every element of list.
coprime_with :: Integer -> [Integer] -> Bool
coprime_with a [] = False
coprime_with a (b:bs) = if ((coprime a b) == True) then
(coprime_with a bs)
else False
希望这不会让人感到困惑。请不要给我答案。只是让我知道我做错了什么以及如何解决它。谢谢!
编辑:好的,我明白了!非常感谢您的回复。它非常快。我是Comp Sci专业,这是我的第一个学期。我的目标是实际学习,而不仅仅是通过它。感谢您的回复以及您的措辞。我的问题是:
coprime_with a [] = False
应该是这样的:
coprime_with a [] = True
现在它正常运作。 Phew ...我觉得很愚蠢,我花了五个小时写这个功能,但至少我实际上学到了一些东西。再次感谢!
答案 0 :(得分:5)
很高兴您找到了问题所在。您可以从中获得更多的课程。
所以你现在有了
coprime_with :: Integer -> [Integer] -> Bool
coprime_with a [] = True
coprime_with a (b:bs) = if ((coprime a b) == True) then
(coprime_with a bs)
else False
每当您看到 A 然后 B 其他错误 时,您可以将其替换为 < em> A &amp;&amp;的乙强> 的。你知道为什么吗?
每当您看到 A == True 时,您只需将其替换为 A 的即可。你知道为什么吗?
现在我们有了
coprime_with a (b:bs) = (coprime a b) && (coprime_with a bs)
参数a
永远不会改变,但我们不必要地将它传递给每个递归调用。另一方面,我们必须拥有它,因为它是coprime_with
的全部内容。解决方案是引入内部函数,
coprime_with a bs = g bs -- "g" is "coprime_with a"
where
g [] = True
g (b:bs) = coprime a b && g bs
(我们可以在没有括号的情况下编写它,因为Haskell中的功能应用程序具有最高优先级)。
这被称为worker/wrapper transform。它使我们的代码更清晰,并允许编译器执行更多优化。我们的新g
是工作者,coprime_with
是包装g
的包装器。 g
有一个不同的类型,coprime_with
负责为它提供正确的参数(这里只是第二个),并将其结果转换回预期的(这里只是传递它们)。
接下来,我们可以在Haskell中为我们想要的任何(子)表达式赋予一个新名称。在这里,我们会做
coprime_with a bs = g pred bs -- "pred" is for "predicate"
where
g pred [] = True
g pred (b:bs) = pred b && g pred bs
pred = coprime a
这有什么意义?你问,我们回过头来递送额外的递归参数吗?正确!这不是优化,而只是重写,旨在某处。接下来,我们甚至可以替换pred
coprime_with a bs = g (coprime a) bs
where
g :: (a -> Bool) -> [a] -> Bool
g pred [] = True
g pred (b:bs) = pred b && g pred bs
那是我们的目的地。剩下的就是要意识到我们已经重新设计了一个轮子(其中一个轮子)。您可以在searching for g
's type on Hoogle找到它的内容,并检查那里的少数热门匹配的来源,看看哪一个是我们的g
。提示:您已在评论中建议使用它。
现在我们可以清楚地看到为什么必须在空列表中返回True
而不是False
。我们的g
检查谓词是否适用于列表的所有元素。换句话说,如果列表中的某个元素未通过谓词,它必须失败(意味着此处,返回False
) - 否则返回True
!但是空列表中没有元素可以使谓词失败。
(我喜欢此问题的另一种解释是basically says,因为g (a++b) == g a && g b
和a == a ++ []
,它必须包含g a == g (a++[]) == g a && g []
)。
答案 1 :(得分:1)
您正在寻找的答案是改变
coprime_with a [] = False
到
coprime_with a [] = True
当列表进入最后的递归阶段时,它已变成一个空列表。它进入空白阶段的事实意味着列表中的所有数字都是互质的。但是,参数的设置方式是,当列表为空时,它被设置为读取&#34; False&#34;。只需将该条件更改为&#34; True&#34;解决了这个问题。