【发布时间】: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 <- 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 <- powerSet s],因此相当于powerSet s。 -
顺便说一句
powerSet函数:hackage.haskell.org/package/containers-0.6.2.1/docs/… -
是的,但是
Data.Set.Set不是一个单子,并且不会让我使用单子推导来定义Sets。 (所以你的第一个例子不会编译)Data.Set.Monad.Setis 一个单子 -
它并不难看。这真好。请务必使用
fromDistinctAscList而不是fromList。这个假设toList产生有序递增列表,它似乎应该这样做。我希望基于集合的代码不必要地对临时列表进行大量设置。
标签: haskell set monads set-comprehension