List 用Haskell中的列表表示集合理论概念

List 用Haskell中的列表表示集合理论概念,list,haskell,recursion,set,pattern-matching,List,Haskell,Recursion,Set,Pattern Matching,我试图在Haskell(即集合)中定义一个新类型,并使用它来操作输入和输出无序列表而不重复的函数 我走的路对吗?任何建议都是受欢迎的,哪怕是最细微的狡辩。我希望我的代码尽可能优雅 -- generalized membership type Set a = [a] member :: Eq a => a -> [a] -> Bool member x [] = False member x (y:ys) | x == y = True

我试图在Haskell(即集合)中定义一个新类型,并使用它来操作输入和输出无序列表而不重复的函数

我走的路对吗?任何建议都是受欢迎的,哪怕是最细微的狡辩。我希望我的代码尽可能优雅

-- generalized membership

type Set a = [a]

member :: Eq a => a -> [a] -> Bool
member x []                 = False
member x (y:ys) | x == y    = True
                | otherwise = member x ys                

-- elimination of duplicates

noReps :: Set Integer -> Set Integer
noReps []                   = []
noReps (x:xs) | member x xs = noReps xs
              | otherwise   = x : noReps xs

inclusion :: Set Integer -> Set Integer -> Bool
inclusion x y = length [i | i <- x, not (member i y)] == 0

identical :: Set Integer -> Set Integer -> Bool 
identical x y = inclusion x y && inclusion y x

-- membership for sets of sets

setmember :: Set Integer -> Set (Set Integer) -> Bool
setmember [] _                      = True
setmember _ []                      = False
setmember x (y:ys)  | identical x y = True 
                    | otherwise     = setmember x ys   

addsets :: Set Integer -> Set (Set Integer) -> Set (Set Integer)
addsets x y | setmember x y = y
            | otherwise = x:y

-- adding an integer to every member of a sets of sets of integers

addelem :: Integer -> Set (Set Integer) -> Set (Set Integer) 
addelem x y = [noReps (x : i) | i <- y]

-- powerset of the set {1,...,n}

powerset :: Integer -> Set (Set Integer)
powerset 1 = [[], [1]]
powerset x = powerset (x-1) ++ addelem x (powerset (x-1))
——广义成员资格
类型集合a=[a]
成员::Eq a=>a->[a]->Bool
成员x[]=False
成员x(y:ys)| x==y=True
|否则=成员x ys
--消除重复
noReps::设置整数->设置整数
NOREP[]=[]
noReps(x:xs)|成员xxs=noReps-xs
|否则=x:noReps xs
包含::设置整数->设置整数->布尔
包含x y=长度[i | i设置整数->布尔
相同的x y=包含x y和包含y x
--集合集合的成员资格
setmember::Set Integer->Set(Set Integer)->Bool
setmember[]ux=True
setmember[]=False
集合成员x(y:ys)|相同x y=True
|否则=setmember x ys
addsets::Set Integer->Set(Set Integer)->Set(Set Integer)
addset x y | setmember x y=y
|否则=x:y
--向整数集的每个成员添加一个整数
addelem::Integer->Set(Set Integer)->Set(Set Integer)
加法器x y=[noReps(x:i)| i集(集整数)
功率集1=[[],[1]]
功率集x=功率集(x-1)+加法器x(功率集(x-1))
在我看来很不错(正如你所说,这是一个“徒劳的练习”);一件事:你的签名都不需要专门化为整数,任何支持相等(Eq)的东西都可以工作,powerset还需要一个数值(同样,不一定是整数):

noReps::Eq a=>Set a->Set a
包含::Eq a=>Set a->Set a->Bool
相同::Eq a=>Set a->Set a->Bool
setmember::Eq a=>Set a->Set(Set a)->Bool
addsets::Eq a=>Set a->Set(Set a)->Set(Set a)
加法器::等式a=>a->Set(Set a)->Set(Set a)
功率集::(等式a,数值a)=>a->Set(Set a)
所有这些签名都可以工作,而不会改变函数本身的任何内容

(编辑:通常最好使您的签名尽可能通用和多态-不仅允许重用代码,而且通过限制您的函数可以对其参数执行的操作-在这种情况下,签名允许您仅应用==运算符-您可以减少错误/意外影响的风险)


当然,使用列表会使代码变得简单而缓慢——对于现实生活中的代码,您会使用平衡树来表示集合——更复杂,但速度更快;事实上,这就是Haskell自己的集合类型的实现方式。

Haskell实际上已经有了一个
Set
类型。您的只是列表的同义词(不同的列表可以有多个相同的元素,并且具有定义的顺序),并且很多列表函数已经在
Data.List
模块中定义。我知道,这基本上是徒劳的。但是考官要求我们自己定义所有内容。因为你是在征求关于你的方法的一般性建议,而不是问一个关于特定错误或问题的问题,我认为该网站会ld是一个更好的选择。另外,用列表实现集合——特别是在Haskell中——效率很低,因为成员身份检查(集合中最常用的函数之一)是线性的,而不是常数时间。