这可能是另一个简单的Haskell问题。如果我有一些“嵌套”数据类型,例如在此示例代码中:
data Place = Country
| State
| City String
deriving Show
data State = California
| NewYork
deriving Show
data Country = USA
| Canada
deriving Show
我可以合法地制作[国家]类型的[美国,加拿大]或[州]类型的[加利福尼亚州,纽约州]或[地方类型的[城市“a”,城市“b”]等列表]
如何制作像[USA,NewYork]这样的清单,我该怎么办?纽约州是一个地方,美国是一个地方的国家,但是ghci看到美国所以它假定我正在制作一个国家名单(而纽约州是一个国家,因此名单失败)。
我认为我需要某种方式将国家或州置于一个地方,但我对如何实现这一目标感到茫然。
我正在努力避免将状态和国家/地区中包含的数据放入Place类型中,我知道这会使其工作,但是我有相当数量的实际数据,我宁愿不要混淆这一点。
答案 0 :(得分:12)
这是一个更多的输出,使我找出问题:
*Main> [State, State]
[State,State]
*Main> :t State
State :: Place
*Main> :t NewYork
NewYork :: State
这似乎意味着“State”这个词是Place的有效构造函数,而数据State指的是只有California或NewYork的值。
如果稍微更改程序,请执行以下操作:
data Place = Country Country
| State State
| City String
deriving Show
data State = California
| NewYork
deriving Show
data Country = USA
| Canada
deriving Show
然后你可以制作一个列表,例如[Country USA,State NewYork],它的类型是[Place]。使用与第一个示例中相同的单词两次不会以我认为的方式将State类型“绑定”在一起。
当然,使用构造函数State State只是一个偏好问题,如果我愿意,我可以轻松地在Place类型中AmericanState State
。
答案 1 :(得分:7)
{-# LANGUAGE ExistentialQuantification #-}
data GenericPlace = forall a. Show a => GenericPlace a
places :: [GenericPlace]
places = [GenericPlace USA, GenericPlace NewYork]
有关此方法的一些限制,请参阅GHC user guide # 7.4.4 Existentially quantified data constructors。
对在Haskell中制作可用的异构集合进行了深入的研究。
Strongly typed heterogeneous collections
异构集合是一种数据类型,能够存储不同类型的数据,同时提供查找,更新,迭代等操作。存在各种异构集合,表示,不变量和访问操作不同。我们描述了HList ---一个用于强类型异构集合的Haskell库,包括可扩展记录。我们在Haskell中的类型安全数据库访问的上下文中说明了HList的好处。 HList库依赖于Haskell 98的常见扩展。我们的探索提出了有关Haskell类型系统的有趣问题,特别是避免重叠实例,以及类型相等和类型统一的具体化。
答案 2 :(得分:4)
您正在构建异构列表(即列表包含不同类型的值)。这种结构可以是静态或动态类型的。无论哪种方式,只要我们知道该值支持特定接口,我们就可以在包裹的列表中使用它。
最好的方法,IMO,是通过存在性打字,如ephemient显示: