【发布时间】:2010-07-25 00:47:43
【问题描述】:
我正在将一些 Haskell 代码从使用列表更改为集合。我认为我了解所需的一切,但我不确定如何在集合上进行模式匹配。列表有这种很好的文字语法,似乎很难用 Set 构造函数来模拟。例如,我可能有一些这样的代码:
foo [] = []
foo x = other_thing
如何编写此代码以使其使用集合而不是列表?
【问题讨论】:
我正在将一些 Haskell 代码从使用列表更改为集合。我认为我了解所需的一切,但我不确定如何在集合上进行模式匹配。列表有这种很好的文字语法,似乎很难用 Set 构造函数来模拟。例如,我可能有一些这样的代码:
foo [] = []
foo x = other_thing
如何编写此代码以使其使用集合而不是列表?
【问题讨论】:
import qualified Data.Set as Set
foo set
| Set.null set = bar
| otherwise = baz
【讨论】:
嗯,你不能。
Set 是一种抽象数据类型[0],它故意隐藏其内部表示,主要是为了保持不能静态的数据结构的不变量——由类型系统强制执行(具体来说,标准库Data.Set.Set 是二叉搜索树)。
失去对抽象数据类型进行模式匹配的能力是一种令人不快的附带损害,但是哦,好吧。您的选择大致是:
null,正如 trinithis 的回答。Set 转换为列表。大多数情况下,这很愚蠢,但如果你想遍历集合,它就足够了。ViewPatterns extension,它为使用访问器函数提供了语法糖,通常会使用模式匹配。Set,请将其视为 set,并将其作为一个整体用于映射、过滤等。并非总是可行,但可以通过更少的显式条件/迭代生成更简洁的代码。查看模式可以让您编写如下所示的内容:
foo (setView -> EmptySet) = []
foo (setView -> NonEmpty set) = other_thing
...setView 是您编写的函数。这里并没有太大的收获,但对于更复杂的伪模式可能会很好
为了避免显式检查,除了众所周知的集合操作,如union 和intersection,考虑使用Data.Set 中的filter、partition、map 和fold 函数.
[0]: 请参阅this paper(警告:PDF)了解我使用的术语的定义。
【讨论】: