努力学习Haskell,如何将字符串的头部与下一个字符进行比较,直到它找到一个注明为真的字符?
在伪代码中我试图:
当x =='字符串中的下一个字符'放入要返回的新列表
答案 0 :(得分:4)
一般方法是创建一个递归计算字符串头部的函数,直到找到false值或到达结尾。
要做到这一点,你需要
我有notes on Haskell你可能觉得有用,但你可能会发现Yet Another Haskell Tutorial更全面(章节 3.3列表; 3.5函数;并且 7.8更多列表可能是开始以便解决我提到的要点的好地方。
<强> EDIT0:强> 使用防护装置测试头部元素并仅在与第二个元素相同时继续的示例:
someFun :: String -> String
someFun[] = []
someFun [x:y:xs]
| x == y = someFun(y:xs)
| otherwise = []
EDIT1:
我想说x =(newlist)然后而不是否则= []否则= [newlist]如果有意义的话? 它在命令式编程范例(例如C或Java)中是有意义的,对功能方法则不那么重要
这是一个具体的例子,希望强调引用建议的 if,then,else 概念与SomeFun
函数中发生的事情之间的差异:
当我们致电SomeFun [a,a,b,b]
时,我们将其与SomeFun [x:y:xs]
相匹配,因为x
为'a',y
为'a',x==y
,然后是SomeFun [a,a,b,b] = SomeFun [a,b,b]
,它再次与SomeFun [x:y:xs]
匹配,但条件x==y
为false,因此我们使用其他保护,因此我们得到SomeFun [a,a,b,b] = SomeFun [a,b,b] = []
。因此,SomeFun [a,a,b,b]
的结果是[]
。
那么数据在哪里?好吧,我会举起手来承认代码中的一个错误,这个错误现在我用来解释Haskell函数是如何工作的。
我发现在构建数学表达式而不是编程操作方面更多地思考是有帮助的。因此,=
右侧的表达式是您的结果,而不是命令式中的赋值(例如Java或C意义上的)。
我希望具体的例子表明Haskell使用替换来计算表达式,所以如果你不想在结果中使用某些东西,那么不要在表达式中包含它。相反,如果您确实需要结果中的某些内容,请将其放在表达式中。
因为你的伪代码是
当x =='字符串中的下一个字符'放入要返回的新列表
我将修改SomeFun函数以执行相反的操作,让您弄清楚如何根据需要修改它。
someFun2 :: String -> String
someFun2[] = []
someFun2 [x:y:xs]
| x == y = []
| otherwise = x : someFun(y:xs)
示例输出:
SomeFun2 [a,a,b,b] = []
SomeFun2 [a,b,b,a,b] = [a]
SomeFun2 [a,b,a,b,b,a,b] = [a,b,a]
SomeFun2 [a,b,a,b] = [a,b,a,b]
(我想在这一点上添加,这些不同的代码片段未经过测试,因为我没有编译器可以处理,所以请指出任何错误,以便我可以修复它们,谢谢)
答案 1 :(得分:2)
有两种典型的方法来获得字符串的头部。 head
和模式匹配(x:xs)
。
事实上,the source for the head
function节目只是用模式匹配来定义:
head (x:_) = x
head _ = badHead
我强烈建议您查看Learn You a Haskell # Pattern Matching。它给出了这个例子,这可能会有所帮助:
tell (x:y:[]) = "The list has two elements: " ++ show x ++ " and " ++ show y
注意它的模式如何与(x:y:[])
匹配,这意味着列表必须有两个元素,而不是更多。要匹配较长列表中的前两个元素,只需将[]
换成变量(x:y:xs)
如果选择模式匹配方法,则需要使用递归。
另一种方法是zip xs (drop 1 xs)
。这个小成语会从列表中的相邻对创建元组。
ghci> let xs = [1,2,3,4,5]
ghci> zip xs (drop 1 xs)
[(1,2),(2,3),(3,4),(4,5)]
然后你可以编写一个逐个查看这些元组的函数。它也是递归的,但可以写成foldl
或foldr
。
为了理解Haskell中的递归,再次强烈推荐LYAH: