Haskell:一直在写一个复制'elem'的函数`
在haskell的第一堂课中,我们给出了一系列的问题。其中之一是当列表中存在n个数字时返回True,否则返回False。我成功地得到了我认为是一半的东西,但是我得到了不同的编译错误,我非常沮丧,因为我甚至可以理解它们的意思 到目前为止,我已经做了以下工作Haskell:一直在写一个复制'elem'的函数`,haskell,pattern-matching,list-comprehension,Haskell,Pattern Matching,List Comprehension,在haskell的第一堂课中,我们给出了一系列的问题。其中之一是当列表中存在n个数字时返回True,否则返回False。我成功地得到了我认为是一半的东西,但是我得到了不同的编译错误,我非常沮丧,因为我甚至可以理解它们的意思 到目前为止,我已经做了以下工作 // No problem with this function matches :: Int -> [Int] -> [Int] // This function is to return the matches matc
// No problem with this function
matches :: Int -> [Int] -> [Int] // This function is to return the matches
matches x y = [a | a <-y, a==x] // ie. main> 1 [1,3,5,7,1,4] outputs [1,1]
// Here am stuck
myelem :: Int -> [Int] -> Bool
myelem x [] = False
myelem x (y:ys)
| x == y = y : x myelem ys // Am not sure about recursion as
// we have not yet covered
//此函数没有问题
matches::Int->[Int]->[Int]//此函数用于返回匹配项
匹配xy=[a | a1[1,3,5,7,1,4]输出[1,1]
//我被卡住了
迈勒姆::Int->[Int]->Bool
myelem x[]=False
迈勒姆x(y:ys)
|x==y=y:x myelem ys//我不确定递归是否为
//我们还没有涵盖
显然,这是针对一个类,所以请不要发布答案。但也许有几个例子可以帮助我解释Haskell的工作原理以及如何解决问题。任何指针都将受到极大的赞赏
解决方案
matches :: Int -> [Int] -> [Int]
matches x y = [a | a <-y, a==x]
myelem :: Int -> [Int] -> Bool
myelem x [] = False
myelem x (y:ys)
| x == y = True
| otherwise = myelem x (ys)
匹配::Int->[Int]->[Int]
匹配xy=[a | a[Int]>Bool
myelem x[]=False
迈勒姆x(y:ys)
|x==y=True
|否则=myelem x(ys)
干杯,伙计们,事实上你们已经非常接近正确的答案了。不过,我看到了两个主要问题。一个是,在最后一行代码中对
myelem
的调用需要加上反引号,使其成为中缀(x`myelem`ys
),或者是一个没有反引号的前缀调用(myelem x ys
)。此外,您不希望在递归调用的结果前面加上y
。实际上,您不需要在第二个模式上加上条件:只需考虑MyLem x(y:ys)是什么应该使用简单的布尔运算和已有的递归调用返回。您尝试在最后一行包含一个Int
和一个Bool
,请三思
您从myelem
中永远不会返回True
;有时它是合适的
一旦这些问题得到解决,代码就会工作。问题出现在您的上一个等式中:
myelem x (y:ys)
| x == y = y : x myelem ys
这里有两个问题:
myelem
作为中缀运算符,则必须将其用倒钩环绕,如下所示:
x `myelem` ys
(:)
要求其第二个参数是一个列表,而不是Bool
。此外,(:)
构造一个列表,myelem
应该返回一个Bool
想想你要做什么。如果
x==y
,你只想返回True
,对吗?否则,你想返回检查列表其余部分的结果(ys
)。希望有帮助。请注意,您还可以根据匹配项定义myelem
函数
- 如果项目不在列表中,匹配项将返回什么
- 如果项目在列表中一次、两次或多次,匹配项将返回什么
- 您是否关心第二种情况下的整个返回值?(提示:否)
您还可以使用以下函数的组合编写函数(使用以下函数至少有两种方法):
从列表中删除元素,除非它们满足某些条件集
null :: [a] -> Bool
返回列表是否为空
not :: Bool -> Bool
这是逻辑否定
or :: [Bool] -> Bool
如果布尔列表包含一个或多个真值,则返回真
显然,你已经解决了你的问题,但它可能会帮助你探索做同样事情的其他方法。@pelotom,@Jeremiah Willcock,@9000:谢谢这么多人,我只是发现将我的推理从命令式转换为声明式非常有挑战性
执行时,它实际上是从列表中删除元素直到为空,还是只是计算列表中的剩余元素直到没有剩余?@Carlos:在Haskell这样的纯函数语言中,函数永远不能“删除”任何东西,因为这都是一种副作用,违反了纯粹性。为了了解函数列表是如何工作的,可以将它以嵌套的形式写出来:[1,2,3,4]
实际上是1:(2:(3:[]))
。换句话说,这个列表由另一个列表前面的1
组成,2:(3:[])
,它又由另一个列表前面的2组成,依此类推。每个内部列表都“不知道”引用它的外部列表。@Carlos:例如,让xs=[1,2,3]在(4:xs,5:xs)
中,…这会产生一对列表,([4,1,2,3],[5,1,2,3])
,它们共享同一个内部列表xs 1,2,3]
。作用于列表的递归函数反映了这种嵌套形式。它们在类似于x:xs
的列表上进行模式匹配,对x
执行操作,在内部列表xs
上递归,依此类推,直到在[]处触底
。模式匹配不会改变任何东西,它只是简单地将列表分析为其组成部分。@pelotom:哇,伙计,非常感谢你对我的问题所做的大量解释、时间和努力。祝你好运。每当你有一个函数每次查看列表中的项目并吐出一些东西时,foldr通常是一个很好的方法。我建议您重新编写函数,因为这是一个很好的练习,有助于您熟悉Haskell和函数编程思想。
or :: [Bool] -> Bool