【问题标题】:Haskell Set ComprehensionsHaskell 集合理解
【发布时间】:2015-10-29 17:38:35
【问题描述】:

是否有任何可能性(例如语言扩展)使用Data.Set 集合的列表推导语法的语法?

示例:

f :: Set a -> Set b -> Set (a,b)
f xs ys = [(x,y) | x <- xs , y <- ys] -- this is the set comprehension

由于集合是启发列表推导的数学结构,所以没有任何可能在集合上使用它们会有点奇怪。

是的,我知道MonadComprehensions 可以将list-comp 语法与任何Monad/MonadPlus 类型一起使用,但是由于大多数函数中的Ord 约束,AFAIK 集甚至不能是单子。

【问题讨论】:

  • sets are the mathematical structure that inspired list comprehensions 但是Data.Set不是那个结构because of the Ord constraint

标签: list haskell set list-comprehension


【解决方案1】:

理论上,没有

没有允许“集合理解”的语言扩展。

SetList 之间的区别是:

  1. Set 是无序的,而 List 是有序的
  2. Set 的元素是唯一的,而 List 可能有重复的元素
  3. Set 的类型是Ord 的一个实例,而List 没有类型限制。

您可以看到所有可能的Sets 都是所有可能的Lists 的严格子集。这意味着我们可以简单地使用列表理解并将其转换为Set 来实现“集合理解”。惰性求值经常会使“集合生成”从大多数有限列表推导中高效派生。但是,导致无限列表的列表推导不太可能导致有效的“集合推导”。

示例:

import Data.Set

set :: Ord a => Set a
set = fromList [x * y | x <- [1..10], y <- [1..10]]

在实践中,是的

使用set-monad 包,您可以将Set 定义为Monad 的实例,并使用语言扩展MonadComprehensions 可以实现“集合理解”。

示例:

{-# LANGUAGE MonadComprehensions #-}
import Data.Set.Monad

set1 :: Set (Int,Int)
set1 = do 
         a <- fromList [1 .. 4]
         b <- fromList [1 .. 4]
         return (a,b)

-- Look a "set comprehension"
set2 :: Set (Int,Int)
set2 = [ (a,b) | (a,b) <- set1, even a, even b ]

使用对您的项目最有意义的方法。在做出决定之前对两者进行分析!

【讨论】:

  • Err...惰性求值如何提高集合生成的效率?您必须评估所有列表才能创建集合。懒惰的评估在这里似乎根本没有做任何事情。
  • @Cubic 您不会生成整个列表然后生成整个集合。由于惰性求值,该操作将融合,因此如果我生成单个元素的重复项的大型列表,则不会产生内存开销,因为该集合将从列表中延迟提取并创建单例集合。
  • 取决于 fromList 的实现,在最好的情况下,如果有很多运气和一点乐观,如果列表很大,惰性可以让 GC 有机会扫过列表的头部,而尾巴被喂给了集合建造者。但在现实世界中,我怀疑确实会产生任何影响。
  • 在无限输入上发散的函数不会被大多数人称为惰性函数。
  • @MathiasDolidon 也许是FoldableListLike。如果可以泛化Foldable 的实例以允许任意“列表理解”语法,那将会很有趣。
猜你喜欢
  • 2021-01-04
  • 2014-03-13
  • 2015-12-24
  • 1970-01-01
  • 2011-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多