List Haskell:创建列表以评估列表元素
我试图编写一个list函数,它接受一个简单的列表并反馈一个列表列表,后者的所有元素都与前一个元素具有相同的关系 更具体地说,职能部门应该做到这一点:List Haskell:创建列表以评估列表元素,list,haskell,List,Haskell,我试图编写一个list函数,它接受一个简单的列表并反馈一个列表列表,后者的所有元素都与前一个元素具有相同的关系 更具体地说,职能部门应该做到这一点: 拿一张单子设xs=[1,2,3,4,5,6,8,9,10] 从头部看两个元素,如果第二个元素等于第一个元素加上一个元素(即,xs!!0=xs!!1-1),则从中创建一个列表 列表接受元素,而最后一个元素与从主列表新输入的元素具有相同的关系。当出现中断时,子列表关闭,但函数应始终基于相同的条件创建一个新的子列表 因此,最终结果应该是,[[1,2,3,
设xs=[1,2,3,4,5,6,8,9,10]
xs!!0=xs!!1-1
),则从中创建一个列表[[1,2,3,4,5,6],[8,9,10]
缺少的7将主列表分为两个子列表。它们都是算术级数,其公共差为1ghci> filter (\x y -> x + 1 == y) xs
"<"interactive">":1:8:
The lambda expression `\ x y -> x + 1 == y' has two arguments,
but its type `a -> Bool' has only one
In the first argument of `filter', namely `(\ x y -> x + 1 == y)'
In the expression: filter (\ x y -> x + 1 == y) xs
In the definition of `it': it = filter (\ x y -> x + 1 == y) xs
ghci>过滤器(\x y->x+1==y)xs
"":1:8:
lambda表达式“\x y->x+1==y”有两个参数,
但是它的'a->Bool'类型只有一个
在“filter”的第一个参数中,即“(\x y->x+1==y)”
在表达式中:filter(\x y->x+1==y)xs
在“it”的定义中:it=filter(\xy->x+1==y)xs
对于您的错误:过滤器的类型是(a->Bool)->[a]->[a]
。lambda有两个参数,filter
需要一个一元函数
您想要的函数(据我所知)是groupBy::(a->a->Bool)->[a]->[[a]]]
遗憾的是,使用pmr建议的groupBy
将无法工作,因为它与每个组的第一个元素进行比较,而不是比较相邻的元素。这是因为groupBy
假设等式谓词是可传递的。通过使用此更改版本,您可以获得所需的行为:
groupBy rel [] = []
groupBy rel (x:xs) = (x:ys) : groupBy rel zs
where (ys,zs) = groupByAux x xs
groupByAux x0 (x:xs) | rel x0 x = (x:ys, zs)
where (ys,zs) = groupByAux x xs
groupByAux y xs = ([], xs)
另请参见:。好的,将比较函数放在GHCi中,看看它为类型提供了什么:
Prelude> :t (\x y -> x + 1 == y)
(\x y -> x + 1 == y) :: Num a => a -> a -> Bool
但是filter
的谓词具有类型(a->Bool)
;这是行不通的,因为它一次只查看一个元素。你需要一些类似过滤器的东西,但要有
(a->a->Bool)->[a]->[a]]
时间。(或者,如果您愿意的话)
Hoogle对这种类型签名的第一个匹配是,这正是您要寻找的函数
不幸的是,正如您所发现的那样,groupBy
并不完全正确。问题在于,它将每个新元素与它测试的第一个元素进行比较,因此通过输入[1,2,3]
,当比较1和2时,测试函数返回True
,而当比较1和3时返回False
。但是,如果您查看实现,可能会对其进行一些修改
groupBy :: (a -> a -> Bool) -> [a] -> [[a]]
groupBy _ [] = []
groupBy eq (x:xs) = (x:ys) : groupBy eq zs
where (ys,zs) = span (eq x) xs
嗯。这使用span
来划分列表,在这里不起作用,因为span
一次只查看一个参数。您可以按照哈马尔的建议修改groupBy
,但您也可以用其他方式编写它,比如使用foldr
:
myGroupBy _ [] = []
myGroupBy eq (x:xs) = (\(_,t1,t2) -> init $ t1:t2) $ foldr (\el (el2,t1,t2) ->
if eq el el2
then (el,el:t1,t2)
else (el,[el],t1:t2))
(x,[],[]) (x:xs)
这是我对这个问题的思考过程。。。我们想把一个列表分割成“链”(也就是一个列表列表),给出一个测试,看看两个元素是否链接在一起
chains :: (x -> x -> Bool) -> [x] -> [[x]]
我不记得图书馆里有这样的东西,所以我决定自己动手。我想确定一个合适的递归策略来处理列表
我可以只考虑元素吗?否:我很快排除了map
和foldMap
,因为在这个问题中,元素似乎不是彼此独立处理的
接下来,我问“输出类型是否有列表代数?”。这听起来可能不是一件显而易见的事情,用这种方式来表达,但它揭示了以下明智的问题。是否存在建立输出(链列表)而不是输入(列表)的“无”和“cons”操作?如果是这样,我可以使用foldr
将输入nil和cons转换为输出nil和cons,如下所示
chains :: (x -> x -> Bool) -> [x] -> [[x]]
chains link = foldr chCons chNil where
-- chNil :: [[x]]
-- chCons :: x -> [[x]] -> [[x]]
很明显,当我对原始元素进行分组时,chNil
必须是什么。空进来?清空
chains :: (x -> x -> Bool) -> [x] -> [[x]]
chains link = foldr chCons [] where
-- chCons :: x -> [[x]] -> [[x]]
我可以写chCons
?假设我得到一个链列表:如何添加新元素?好吧,如果有一个前端链我可以链接,那么我应该扩大该链,否则我应该开始一个新的链。所以我在非空链列表的开头有一个非空链的特例,默认为cons singleton
chains :: (x -> x -> Bool) -> [x] -> [[x]]
chains link = foldr chCons [] where
chCons y (xs@(x : _) : xss) | link y x = (y : xs) : xss
chCons y xss = [y] : xss
我们到家了
> chains (\ x y -> x + 1 == y) [1,2,3,4,5,6,8,9,10]
[[1,2,3,4,5,6],[8,9,10]]
如果可以为给定类型的值实现这些运算符,则一组运算符具有该类型的代数。数据类型的构造函数只是一个代数,一组运算符的一个实现,在该数据类型中构建值。使用数据类型的输入进行计算的一个好方法是实现所需输出类型的代数。foldr
的重点是捕捉这种“发现代数”模式,这正是解决这个问题的关键。嘿,我在发布后几分钟就意识到了这一点。然后再一次,ghci>groupBy(\xy->x+1==y)xs[[1,2],[3,4],[5,6],[8,9],[10]
我记得那个线程;我认为这一变化已经在2010年下半年的基础上进行了。它可能应该回到过去libraries@.Thanks,哈马尔。很好用![仍然不知道如何在注释框中返回]类型推断是:groupByMe::(a->a->Bool)->[a]->[[a]]因此,这是一个检查二进制谓词上的列表以生成列表的函数。我也会开始阅读你的链接。[仍然不知道这里是否有私人信息系统]。感谢dave修改了我上面第一篇文章的格式。什么是|
和x0
?除此之外,您的代码似乎