Haskell数据类型列表

Haskell数据类型列表,haskell,types,Haskell,Types,这可能是另一个简单的哈斯克尔问题。如果我有一些“嵌套”数据类型,例如在本示例代码中: data Place = Country | State | City String deriving Show data State = California | NewYork deriving Show data Country = USA | Canada

这可能是另一个简单的哈斯克尔问题。如果我有一些“嵌套”数据类型,例如在本示例代码中:

data Place = Country
           | State
           | City String
           deriving Show

data State = California
           | NewYork
           deriving Show

data Country = USA
             | Canada
             deriving Show
我可以合法地制作一份清单,例如[国家]类型的[美国、加拿大],或[州]类型的[加利福尼亚、纽约],或[地点]类型的[城市“a”,城市“b”]

我要做什么才能列一个清单,比如[美国,纽约]?纽约是一个地方所在的州,美国是一个地方所在的国家,但ghci看到了美国,所以它认为我在列一个国家的清单(而纽约是一个州,所以清单失败)

我想我需要一些方法来将一个国家或州铸造成一个地方,但我对如何实现这一点感到困惑


我试图避免将州和国家中包含的数据放入Place类型,我知道这会使它正常工作,但我有相当数量的真实数据,我不希望像那样乱七八糟。

这里有一点更多的输出,让我找出了问题:

*Main> [State, State]
[State,State]
*Main> :t State
State :: Place
*Main> :t NewYork
NewYork :: State
这似乎意味着单词“State”是Place的有效构造函数,并且数据状态仅指加利福尼亚或纽约的值

如果您稍微更改程序,请更改为:

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只是一个偏好问题,如果我愿意的话,我也可以在Place类型中轻松地执行
AmericanState

{-# LANGUAGE ExistentialQuantification #-}
data GenericPlace = forall a. Show a => GenericPlace a
places :: [GenericPlace]
places = [GenericPlace USA, GenericPlace NewYork]
有关此方法的一些限制,请参见


在Haskell中有一项关于创建可用异构集合的深入研究

异构集合是一种数据类型,能够存储不同类型的数据,同时提供查找、更新、迭代等操作。存在各种各样的异构集合,它们在表示、不变量和访问操作方面有所不同。我们描述HList——一个用于强类型异构集合(包括可扩展记录)的Haskell库。我们将在Haskell中类型安全数据库访问的上下文中说明HList的优点。HList库依赖于Haskell 98的通用扩展。我们的探索提出了有关Haskell类型系统的有趣问题,特别是避免重叠实例,以及类型平等和类型统一的具体化


您正在构建一个异构列表(即,该列表包含不同类型的值)。这样的结构可以是静态或动态类型。无论哪种方式,只要我们知道该值支持特定接口,就可以在列表包装中使用它

IMO,最好的方法是通过存在类型,如ephemient所示:

  • 所有值都支持显示界面
  • 任何支持Show的内容都可以放在列表中
  • 类型系统保证您不能破坏抽象

哦,这就是你绊倒的地方吗?是的,构造函数和类型都以大写字符开头,但在不同的名称空间中。是的,这是一个真正的初学者的错误。。。希望其他人也会发现它很有用。变量名(和类型变量名)是较低的首字母(或非“:”初始符号),构造函数名是较高的首字母(或“:”)-初始符号),类型名(和模块名)是较高的首字母;这些类别之间没有重叠。希望你不会花太长时间去适应它:)