我想要做的是在Haskell中创建一个类型Set来表示一个通用(多态)集ex。 {1,'x',"aasdf",Phi}
首先我要清楚在我的程序中我想将Phi(空集)视为属于所有集合的东西
这是我的代码
data Set a b= Phi | Cons a (Set a b)
deriving (Show,Eq,Ord)
isMember Phi _ = True
isMember _ Phi = False
isMember x (Cons a b) = if x==a
then True
else isMember x b
我面临着一些问题:
我希望isMember
类型为
isMember :: Eq a => a -> Set a b -> Bool
但根据我的代码,它是
isMember :: Eq a => Set a b -> Set (Set a b) c -> Bool
如果我有一组不同的时间==
运算符无法正常工作,那么我需要一些帮助:D
答案 0 :(得分:6)
关于你的类型错误,问题看起来像我的第一个句子:
isMember Phi _ = True
这是一个要编写的奇数子句,因为Phi
是整个集合,而不是集合元素。只是删除它应该给你一个你期望的类型的功能。
观察到你的Set
类型从不使用它的第二个类型参数,所以它可以改为编写为
data Set a = Phi | Cons a (Set a)
......那时你应该只使用[a]
,因为它是同构的,并且已经为使用和滥用它们而编写了大量函数。
最后,你要求能够把不同类型的东西放进去。简短的回答是Haskell并没有真正摆脱那种方式。这一切都是为了确切地知道什么类型的东西在编译时,这与你的建议并不完全兼容。实际上有一些方法可以做到这一点;但是,我强烈建议在尝试取消债券之前,先熟悉Haskell特有的类型束缚品牌。
答案 1 :(得分:5)
A)这样做几乎总是不是你真正想要的。
B)通过嵌入动态类型(Dynamic
)到使用非常复杂的类型(HList
),有多种方法可以做到这一点。
C)这是一个描述一些方法和问题的页面:http://www.haskell.org/haskellwiki/Heterogenous_collections
D)如果您真的要这样做,我建议HList
:http://homepages.cwi.nl/~ralf/HList/
E)但是如果你开始查看文档/ HList文件并发现自己无可救药地混淆了,那就回到动态解决方案(或者更好的是,重新考虑你为什么需要这个),并在你显着的时候回到HLists更适合Haskell。
(哦,是的,该页面上描述的存在主义解决方案可能是一个糟糕的主意,因为它几乎从未对你做过任何特别有用的事情。)
答案 2 :(得分:2)
您尝试做的事情非常困难,因为默认情况下Haskell不存储任何类型信息。对这些事情非常有用的两个模块是Data.Typeable
和Data.Dynamic
。它们支持存储单态(!)类型并支持动态单态输入。
我之前没有尝试过这样的代码,但我有一些想法可以实现: