【发布时间】:2015-09-20 23:33:57
【问题描述】:
我在 Haskell 中有一个字符串列表,我需要在另一个列表中获取那些长度为奇数的元素。如何使用高阶函数(如 foldr、foldl、foldr1、foldl1、filter、map 等)来完成此操作?我将非常感谢您的帮助。在这种情况下可以使用列表推导吗?
【问题讨论】:
标签: haskell higher-order-functions
我在 Haskell 中有一个字符串列表,我需要在另一个列表中获取那些长度为奇数的元素。如何使用高阶函数(如 foldr、foldl、foldr1、foldl1、filter、map 等)来完成此操作?我将非常感谢您的帮助。在这种情况下可以使用列表推导吗?
【问题讨论】:
标签: haskell higher-order-functions
您似乎知道filter 的存在(因为您已经提到过),但可能不确定它是如何工作的。如果您尝试提取列表的特定子集,这似乎是正确的路径。如果您查看它的类型签名,您会发现它非常简单:
(a -> Bool) -> [a] -> [a]
也就是说,它需要一个返回 True 或 False 的函数(即 true 包含在新集合中,否则为 false)并生成一个新列表。同样,Haskell 在 Prelude 中提供了一个名为 odd 的函数。它的签名如下:
Integral a => a -> Bool
也就是说,它可以接受任何Integral类型,如果是奇数则返回True,否则返回false。
现在,让我们考虑一个解决方案:
filter odd [1..10]
这将提取 [1,10] 之间的所有奇数。
我注意到你提到了列表推导。如果您已经获得了一个列表并且您只是在过滤它,您可能不想使用它。然而,列表推导将是一个完全可以接受的解决方案:
[x | x <- [1..10], odd x]
通常,列表推导式用于表达具有更复杂约束的列表的生成。
现在,实际回答您的问题。因为我们知道我们可以过滤数字,并且如果我们使用 Hoogle 搜索以下类型(注意 String 就是 [Char]):
[a] -> Int
您将看到一个length 函数。通过一些函数组合,我们可以快速了解如何创建一个过滤奇数长度的函数。总而言之,我们有odd,它是Int -> Bool(在这种情况下)类型,我们有length,它是[a] -> Int 或者——特别是——String -> Int。我们的解决方案现在如下所示:
filter (odd . length) ["abc","def","eh","123","hm","even"]
【讨论】:
来吧。
getOddOnes = filter . flip (foldr (const (. not)) id) $ False
注意:如果你把这个作为你的作业,你最好准备好解释它!
【讨论】:
isOddLength 部分却是不必要的复杂。一个更简单的解决方案是getOddOnes = filter $ foldr (const not) False