【问题标题】:How to define powerset in Data.Set.Monad?如何在 Data.Set.Monad 中定义 powerset?
【发布时间】:2020-06-07 10:12:31
【问题描述】:

Data.Set.Monad{-# LANGUAGE MonadComprehensions} 一起使用时,可以定义集合 几乎就像我们在高中时所做的那样,我们使用 {x ∈ S | φ(x)} 之类的推导来定义集合。例如:

s' = [x | x <- s, phi(x)]

不可能使用更广​​泛使用的Data.Set 模块,因为它的Set 类型构造函数不是monad。

最近在拼凑一个玩具示例时,我需要 powerset Powerset(S) = {x | x ⊆ S} 问题是这个定义没有使用“生成器”x &lt;- Y,这在集合论中不是问题,但在 monad 理解中是必需的:

powerset s = [ x | x `isSubsetOf` s ]

只是无法编译 (error: Variable not in scope: x)

可以将集合转换为列表,获取其所有子列表的列表,将此列表转换回集合,然后也将其所有元素转换为集合:@ 987654333@。但这感觉就像一个丑陋的黑客攻击

{-# LANGUAGE MonadComprehensions #-} 
import Prelude hiding (map)
import Data.List hiding (map)
import Data.Set.Monad 

powerset :: Ord a => Set a -> Set (Set a)
powerset =  (map fromList) . fromList. subsequences . toList

oneToTen = fromList [1..10]
smallEvens = [x | x <- oneToTen, even x, x < 6] -- just like in high school!

statement = smallEvens `member` powerset oneToTen

main :: IO()
main = putStrLn $ if statement == True  then "yes" else "no"

... 将按预期编译并打印“yes”。

有人有更优雅的解决方案吗?

【问题讨论】:

  • Powerset(S) = {x | x ⊆ S} 仅等同于 [x | x &lt;- powerSet s],因此相当于 powerSet s
  • 是的,但是Data.Set.Set 不是一个单子,并且不会让我使用单子推导来定义Sets。 (所以你的第一个例子不会编译)Data.Set.Monad.Set is 一个单子
  • 它并不难看。这真好。请务必使用fromDistinctAscList 而不是fromList。这个假设toList 产生有序递增列表,它似乎应该这样做。我希望基于集合的代码不必要地对临时列表进行大量设置。

标签: haskell set monads set-comprehension


【解决方案1】:

这是一个利用 monad 理解的简单递归解决方案:

powerset :: Ord a => Set a -> Set (Set a)
powerset s = insert s [x | elem <- s, let rest = delete elem s, x <- powerset rest]

【讨论】:

    猜你喜欢
    • 2014-01-04
    • 2017-08-09
    • 1970-01-01
    • 1970-01-01
    • 2019-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多