我正在尝试编写一个列表函数,它采用一个简单的列表并反馈一个列表列表,所有后者的元素与前一个元素具有相同的关系.
更具体地说,函数应该这样做:
let 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将主要列表分为两个子列表.它们都是算术进展,常见差异为1.在第7章阅读了" 了解你的大好事"之后,我认为自己确实有了一个好主意,并且尝试过并且不光彩地失败了.欢迎帮助,拜托!
ghci> 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
Run Code Online (Sandbox Code Playgroud)
这是我对这个问题的思考过程......我们想把一个列表切成'链'(所以是一个列表列表),给出一个测试,看两个元素是否链接起来.
chains :: (x -> x -> Bool) -> [x] -> [[x]]
Run Code Online (Sandbox Code Playgroud)
我不记得图书馆里有这样的东西,所以我决定自己动手.我想确定一个合适的递归策略来处理列表.
我能想到元素吗?不,我迅速排除map,并foldMap作为元素似乎没有在这个问题上要相互独立的处理.
接下来,我问'输出类型是否有列表代数?'.这可能听起来不是一个明显的想法,用这种方式表达,但它解开了以下明智的问题.是否存在构建输出(链表)而不是输入(列表)的'nil'和'cons'操作?如果是这样,我可以使用foldr将输入nil-and-cons转换为输出nil-and-cons,就像这样.
chains :: (x -> x -> Bool) -> [x] -> [[x]]
chains link = foldr chCons chNil where
-- chNil :: [[x]]
-- chCons :: x -> [[x]] -> [[x]]
Run Code Online (Sandbox Code Playgroud)
很明显是什么chNil,因为我正在对原始元素进行分组.空了?清空!
chains :: (x -> x -> Bool) -> [x] -> [[x]]
chains link = foldr chCons [] where
-- chCons :: x -> [[x]] -> [[x]]
Run Code Online (Sandbox Code Playgroud)
我可以写chCons吗?假设我得到一个链列表:如何添加新元素?好吧,如果有一个前链我可以链接到那么我应该增长该链,否则我应该开始一个新的链.所以我在一个非空链列表的开头有一个非空链的特殊情况,默认情况下是一个单例.
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
Run Code Online (Sandbox Code Playgroud)
我们回家了!
> chains (\ x y -> x + 1 == y) [1,2,3,4,5,6,8,9,10]
[[1,2,3,4,5,6],[8,9,10]]
Run Code Online (Sandbox Code Playgroud)
如果您可以为该类型的值实现这些运算符,则一堆运算符具有给定类型的代数.数据类型的构造函数只是一个代数,一组运算符的一个实现,以非常数据类型构建值.使用数据类型的输入进行计算的一种好方法是为所需类型的输出实现其代数.关键foldr在于捕捉这种"找代数"的模式,这就是为了解决这个问题.