Haskell 创建集合数据类型
所以我需要在Haskell中创建一个集合数据类型 所以,在我问题的第一部分,我需要定义Haskell 创建集合数据类型,haskell,types,Haskell,Types,所以我需要在Haskell中创建一个集合数据类型 所以,在我问题的第一部分,我需要定义 type Set a = ... 我把它设置为 type Set a = Set [a] 因为集合就是一个字母列表,对吗? 或者,正确的方法是什么 type Set a = ([a]) 然后,对于下一部分,我需要实现一个函数 setSuchThat :: (a -> Bool) -> (Set a) 该函数采用特征函数f并返回一个集合,使得值x(适当类型)仅在f(x)为真时才在集合中。因此
type Set a = ...
我把它设置为
type Set a = Set [a]
因为集合就是一个字母列表,对吗?
或者,正确的方法是什么
type Set a = ([a])
然后,对于下一部分,我需要实现一个函数
setSuchThat :: (a -> Bool) -> (Set a)
该函数采用特征函数f并返回一个集合,使得值x(适当类型)仅在f(x)为真时才在集合中。因此,一个正在使用的例子是
setSuchThat (\x -> x == "coke")
所以我现在的问题是,在这个函数中,我需要计算这个函数,得到“coke”,然后把它添加到我的集合中。我想我只是不明白,在这个函数中,我该怎么做。按照Daniel Wagner的建议,可以将集合定义为一个谓词,指示元素是否在集合中:
type Set a = a -> Bool
为了更好地衡量,我将使用newtype
来更清楚地说明我们在哪里使用集合:
newtype Set a = Set { contains :: a -> Bool }
然后setSuchThat
将谓词包装在Set
中:
setSuchThat :: (a -> Bool) -> Set a
setSuchThat = Set
您可以使用contains
功能测试集合中的成员资格:
> setSuchThat (== "coke") `contains` "coke"
True
> setSuchThat (== "coke") `contains` "pepsi"
False
insert :: (Eq a) => a -> Set a -> Set a
insert x s = Set $ \ x' -> x == x' || s `contains` x'
> insert "pepsi" (setSuchThat (== "coke")) `contains` "pepsi"
True
所以空集就是setSuchThat(const False)
——对于任何给定的元素,它总是用“否”回答“集合是否包含此元素?”
然后,通过将现有的contains
函数与新函数组合,您可以实现insert
等功能,以使用新元素扩展集合:
> setSuchThat (== "coke") `contains` "coke"
True
> setSuchThat (== "coke") `contains` "pepsi"
False
insert :: (Eq a) => a -> Set a -> Set a
insert x s = Set $ \ x' -> x == x' || s `contains` x'
> insert "pepsi" (setSuchThat (== "coke")) `contains` "pepsi"
True
其他功能(如union
)很简单:
union :: Set a -> Set a -> Set a
union s1 s2 = Set $ \ x -> s1 `contains` x || s2 `contains` x
> let sodas = setSuchThat (== "coke") `union` setSuchThat (== "pepsi")
> sodas `contains` "coke"
True
> sodas `contains` "pepsi"
True
> sodas `contains` "water"
False
作为练习,尝试实现其他设置函数,如delete
、intersect
和difference
这种方法的一个缺点是,在插入或删除的元素数量上,每次查找都是线性的O(n)。此外,您不能简单地枚举集合的所有元素以将其转换为列表,您只能枚举值并测试每个值是否为元素。然而,一个优点是,这可以让您轻松地表示无限集;例如,setSuchThat(>0)
包含所有非负数
这就是为什么标准的Data.Set
类型使用基于树的数据结构而不是函数,将元素表示为它们的实际值。使用这种方法,可以在不增加集合大小的情况下删除值,并且由于它使用Ord
而不是Eq
,因此它可以实现更高效的对数-O(logn)-查找和插入。基于已布置的内容:
您需要将设置a=a->Bool
视为必须处理的限制。当您查看setSuchThat::(a->Bool)->(Set a)
时,您可以将其读取为与setSuchThat:(Set a)->(Set a)
或setSuchThat:(a->Bool)->(a->Bool)
相同<代码>设置这样有点像mcguffin,它只是为了让函数的使用更加清晰-这是不必要的
您所做的一切就是获取函数
f
并将其应用于变量x
。设置的整个点,即
要通过f
和x
并仅返回f x
查找过滤器的源代码。您将发现setSuchThat=filter
。这是不可能的。有无限多个可能的字符串。程序如何知道它何时具有将返回True
的所有值?一个更现实的解决方案是使用过滤器
。如果您必须实现的唯一功能是setSuchThat
,那么让我建议键入Set A=A->Bool
。然后你会发现setSuchThat
微不足道。是的,我还不完全确定该做什么,但是是的,还有更多的函数需要实现,比如并集和交集。它可以是type Set a=[a]
或data Set a=Set[a]
。如果希望Set
成为一个独特的数据结构,而不仅仅是一个列表的另一个名称,则必须使用后者。您可能希望这样,因为您实际上不希望Set[1]++Set[1]
成为Set[1,1]
,甚至不希望编译。