Haskell 如何停止递归并在内存中生成列表

Haskell 如何停止递归并在内存中生成列表,haskell,recursion,Haskell,Recursion,(1.)函数“sameString”返回一个布尔值,用于判断两个字符串是否相同,而不考虑大小写 -- *Main> sameString "HeLLo" "HElLo" -- True -- *Main> sameString "Hello" "Hi there" -- False sameString :: String -> String -> Bool sameString str1 str2 | length str1 == length

(1.)函数“sameString”返回一个布尔值,用于判断两个字符串是否相同,而不考虑大小写

--  *Main> sameString "HeLLo" "HElLo"
--   True
--   *Main> sameString "Hello" "Hi there"
--   False


sameString :: String -> String -> Bool
sameString str1 str2
    | length str1 == length str2 = and [ a == b | (a,b) <- zip (capitalise str1) (capitalise str2) ]
    | otherwise = False
--  *Main> prefix "bc" "abCDE"
--  False
--  *Main> prefix "Bc" "bCDE"
--  True

prefix :: String -> String -> Bool
prefix [] [] = True
prefix substr str
    | sameString string' substr == True = True
    | otherwise = False
    where chop_str :: String -> String -> String
          chop_str str substr = (take (length substr) str)
          string' = chop_str str substr   
(3.)函数“DropTill”返回第一个字符串首次出现后第二个字符串的内容。如果第二个字符串不包含作为子字符串的第一个字符串,则应返回空字符串

*Main> dropUntil "cd" "abcdef"
"ef"

 dropUntil :: String -> String -> String
 dropUntil substr [] = ""
 dropUntil substr (s:tr)
    | prefix substr (s:tr) == False = drop 1 s : dropUntil substr tr
    | prefix substr (s:tr) == True =  
现在问题来了。我在考虑用递归做dropUntil

我认为上述功能应该做的是:

1) 给定一个字符串和一个子字符串(子字符串不是该字符串的前缀)

它应该把绳子的头放下

并将空列表“”改为

。。。对剩余尾部和相同子字符串的递归调用

其背后的思想是不断删除列表的头,直到子字符串成为列表的前缀,然后函数将生成剩余的字符串作为结果

然而,我不知道该怎么做。我基本上想做的是

| prefix substr (s:tr) == True =  "leftover_string"
其中,“leftover_string”是递归调用删除元素后剩下的内容,直到满足子字符串是余数前缀的条件

这可以按照我开始的方式进行吗?这就是你想要的吗

| prefix substr (s:tr) == True =  drop (length substr) (s:tr)
一些注意事项:

此处存在类型错误:

| prefix substr (s:tr) == False = drop 1 s : dropUntil substr tr
                                  ^^^^^^^^
我想你只是想:

| prefix substr (s:tr) == False = dropUntil substr tr

在过去的几天里,我们遇到了很多问题,其中涉及到运行一个对等的
[x]
和一些其他的
[x]
来查找
isPrefixOf
。从那时起,在我的思维过程中出现的一个原始概念在这里非常有价值:

import Data.List

splitAtSublist :: ([x] -> Bool) -> [x] -> Maybe ([x], [x])
splitAtSublist pred list = find (pred . snd) $ zip (inits list) (tails list)
字符串
“abcd”
的拆分
zip(初始列表)(尾部列表)
看起来像
[(“”,“abcd”),((“a”,“bcd”),(“ab”,“cd”),(“abc”,“d”),(“abcd”,“d”)]
。这将查找第一个元素,其中拆分的“尾端”满足谓词
pred

要在此基础上获得Drop Until s,我们只需执行以下操作:

dropUntil p ls = 
    maybe "" (drop (length p) . snd) $ 
        splitAtSublist (p `isPrefixOf`) ls
其中,
isPrefixOf
来自
数据。列表也是。替换为,我们发现根本不使用
inits列表
,它只是变成:

dropUntil p = maybe "" (drop $ length p) . find (p `isPrefixOf`) . tails

这是我能得到的最简单的

(这个评论是离题的。)请记住,尤其是如果你是学生,“字母”,特别是Unicode,比你想象的要复杂得多。您的函数
capitalize=map toUpper
,尤其是作为不区分大小写比较的代理,被认为是不好的做法。对于真实世界的使用,请考虑使用“谢谢”来指出可怕的类型错误。是的,这正是我的意思,而且很有道理!谢谢User5402提供了我想要的确切答案,但这也非常棒。我是Haskell的初学者,因此我必须查找一些函数,但我大致了解了它的要点。希望我能抽出时间仔细研究你的答案,我真的很感激,克里斯!
dropUntil p = maybe "" (drop $ length p) . find (p `isPrefixOf`) . tails