在haskell中,有没有一种方法可以防止变量在递归内部发生变化?

发布于 2024-08-18 13:13:53 字数 947 浏览 2 评论 0原文

我正在尝试定义 isInfixOf 函数,并且我找到了一个解决方案(希望它能正常工作:-)),
但由于 haskell 的递归性质,我编写了另一个(帮助)函数
几乎重复函数 isInfixOf 的代码。

这是代码:

myIsInfixOf :: (Eq a) =>; [一]-> [一]->布尔 myIsInfixOf [] [] = True myIsInfixOf [] 列表 = True myIsInfixOf 列表 [] = False myIsInfixOf 列表A 列表B | myIsInfixOf helpFunction listA listB == True = True |否则 = myIsInfixOf listA (tail listB)

helpFunction :: (Eq a) => [一]-> [一]->布尔 帮助函数 [] [] = True helpFunction [] 列表 = True 帮助函数列表 [] = False 帮助函数 (x:xs)(y:ys) | x == y = helpFunction xs ys |否则=假

我执行了帮助功能,因为我需要 myIsInfixOf 函数的第一个元素,不可触及。
如果我不创建这个 helpFunction,函数 myIsInfixOf 的第一个元素总是减少一个元素,这不好,因为我需要迭代函数 myIsInfixOf 的整个第二个元素,并检查与第一个元素是否相等它的元素。
在 helpFunction 的帮助下,列表中的第一个元素是不可触及的,只有第二个元素正在减少每次递归(这很好)。

那么,我可以将 myIsInfixOf 的第一个元素保存在某个地方,而不需要重新编码几乎所有内容吗?

谢谢。 :-)

i'm trying to define the isInfixOf function, and i came to a solution(hope it works good :-)),
but because of the recursion nature of haskell, i wrote another (help) function that
almost duplicate the code of the function isInfixOf.

this is the code:

myIsInfixOf :: (Eq a) => [a] -> [a] -> Bool myIsInfixOf [] [] = True myIsInfixOf [] list = True myIsInfixOf list [] = False myIsInfixOf listA listB | helpFunction listA listB == True = True | otherwise = myIsInfixOf listA (tail listB)

helpFunction :: (Eq a) => [a] -> [a] -> Bool helpFunction [] [] = True helpFunction [] list = True helpFunction list [] = False helpFunction (x:xs)(y:ys) | x == y = helpFunction xs ys | otherwise = False

i did the help function, because i need the first element of the myIsInfixOf Function, untouchable.
if i don't make this helpFunction, the first element of the function myIsInfixOf, always decrease by one element, which is not good, because i need to iterate throughout the whole second element of the function myIsInfixOf, and check for equality with the first element of it.
with the help of the helpFunction, my first element of the list is untouchable and just the second element is decreasing every recursion(which is good).

so, can i save somewhere, my first element of myIsInfixOf, without recode almost everything?

thanks. :-)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

甜心小果奶 2024-08-25 13:13:53

如果你仔细观察的话,这两个函数其实并不那么相似。前三个“琐碎”案例是相同的,但最后一个案例在两个函数中执行不同的操作。您还可以在这两个函数中省略前两种情况,因为它们在相同的列表上检查相同的内容。所以 myIsInfixOf 也可以这样工作:

myIsInfixOf :: (Eq a) => [a] -> [a] -> Bool
myIsInfixOf (a:as) [] = False
myIsInfixOf listA listB | helpFunction listA listB = True
                        | otherwise =  myIsInfixOf listA (tail listB)

这确实与 helpFunction 不同,并且不重复任何重要的代码。

另外,您确实希望第二个函数独立于第一个函数工作,因为您希望检查 listB 中的每个位置,如果 listA 的每个字符都与 listB 中的字符匹配。要在命令式程序中执行此操作,您需要嵌套循环,这里您需要一个嵌套递归,最好像您一样使用辅助函数来完成。问题不在于如果没有 helpFunction,listA 会以某种方式丢失,问题在于该算法需要 helpFunction 独立于 myIsInfixOf 运行列表>。

如果您想通过使用标准库中的更多函数来避免手动实现 myIsInfixOf 的递归,您可以使用 anytails。对于 helpFunction 可能显式递归是可行的方法,但您可以将最后一种情况简化为:

helpFunction (x:xs) (y:ys) = (x == y) && helpFunction xs ys

The two functions aren't really all that similar, if you look at them. What is the same are the first three "trivial" cases, but the last case does different things in both functions. You could also leave out the first two cases in either of those functions since they check the same thing on the same lists. So myIsInfixOf also works like this:

myIsInfixOf :: (Eq a) => [a] -> [a] -> Bool
myIsInfixOf (a:as) [] = False
myIsInfixOf listA listB | helpFunction listA listB = True
                        | otherwise =  myIsInfixOf listA (tail listB)

This really isn't the same as helpFunction, and doesn't repeat any nontrivial code.

Also you really want the second function to work independently from the first, since you want to check for every position in listB if every character of listA matches those in listB. To do this in a imperative program you would need nested loops, here you need a nested recursion best done with a helper function like you did. The issue is not that listA would somehow be lost without the helpFunction, the problem is that the algorithm requires helpFunction to run over the list independently of myIsInfixOf.

If you want to avoid manually implementing the recursion of myIsInfixOf by using more functions from the standard library you could use any and tails. For helpFunction probably explicit recursion is the way to go, but you could simplify the whole last case to:

helpFunction (x:xs) (y:ys) = (x == y) && helpFunction xs ys
忱杏 2024-08-25 13:13:53

请注意,1)在这两种情况下都不需要第一个子句,因为 [] list 也匹配 [] [] 并且返回相同的结果; 2) helpFunction listA listB == TruehelpFunction listA listB 相同。

myIsInfixOf :: (Eq a) => [a] -> [a] -> Bool
myIsInfixOf [] list = True
myIsInfixOf list [] = False
myIsInfixOf listA listB | helpFunction listA listB = True
                        | otherwise =  myIsInfixOf listA (tail listB)

helpFunction :: (Eq a) => [a] -> [a] -> Bool
helpFunction [] list    = True
helpFunction list []    = False
helpFunction (x:xs)(y:ys) | x == y = helpFunction xs ys
                          | otherwise = False

你在评论中说

帮助函数检查第一个元素是否在第二个元素内。

事实上,事实并非如此。它检查第二个参数是否以第一个参数开始。这就是为什么你需要一个不同的函数。因此 helpFunction 的更好名称是 myPrefixOf。这应该可以帮助您从 myIsInfixOf 的定义中消除另一个子句。

Note that 1) you don't need the first clause in both cases, since [] list matches [] [] as well and you return the same result; 2) helpFunction listA listB == True is the same as helpFunction listA listB.

myIsInfixOf :: (Eq a) => [a] -> [a] -> Bool
myIsInfixOf [] list = True
myIsInfixOf list [] = False
myIsInfixOf listA listB | helpFunction listA listB = True
                        | otherwise =  myIsInfixOf listA (tail listB)

helpFunction :: (Eq a) => [a] -> [a] -> Bool
helpFunction [] list    = True
helpFunction list []    = False
helpFunction (x:xs)(y:ys) | x == y = helpFunction xs ys
                          | otherwise = False

In the comment you said

the help function examine if the first element is inside the second one.

Actually, it doesn't. It checks if the second argument starts with the first one. That's why you need a different function. So a better name for helpFunction is myPrefixOf. This should help you eliminate another clause from the definition of myIsInfixOf.

芸娘子的小脾气 2024-08-25 13:13:53

根据 Alexey Romanov 等人提出的一些建议,这将是我重写它的初步看法:

import Data.List

myIsInfixOf xs ys = any (myIsPrefixOf xs) (tails ys)

myIsPrefixOf [] _ = True
myIsPrefixOf (x:_) [] = False
myIsPrefixOf (x:xs) (y:ys) = x == y && myIsPrefixOf xs ys

为了更直接地回答您的实际问题,请注意有关此版本的两件事:

  • 您可以“保存”使用部分应用程序的第一个参数
  • 您可以通过使用内置递归函数消除大量冗余代码

In line with a few of the suggestions Alexey Romanov and sth made, this would be my initial take on rewriting it:

import Data.List

myIsInfixOf xs ys = any (myIsPrefixOf xs) (tails ys)

myIsPrefixOf [] _ = True
myIsPrefixOf (x:_) [] = False
myIsPrefixOf (x:xs) (y:ys) = x == y && myIsPrefixOf xs ys

To more directly answer your actual question, note two things about this version:

  • You can kind of "save" the value of the first argument using partial application
  • You can eliminate a lot of the redundant code by using built-in recursive functions
冷…雨湿花 2024-08-25 13:13:53

我认为您在问题中混淆了“元素”和“论证”,至少在某些地方是这样。另外,你所说的“不可触碰”是什么意思?

回到你的问题:你可以使用所谓的 at-patterns 进行模式匹配并保留原始参数:

myIsInfixOf listA@(x:xs) listB@(y:ys) = ...

这使你可以将整个第一个参数称为 listA,将 listA 的第一个元素称为 x 和尾部作为 xs (与第二个参数相同)。这就是你的意思吗?

I think you're confusing 'element' and 'argument' in your question, at least in some places. Also, what do you mean by 'untouchable'?

To come back to your question: You can do a pattern match and keep the original argument around by using so-called at-patterns:

myIsInfixOf listA@(x:xs) listB@(y:ys) = ...

This lets you refer to the entire first argument as listA, the first element of listA as x and the tail as xs (and same for the second argument). Is that what you meant?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文