【问题标题】:Haskell generic data structureHaskell 通用数据结构
【发布时间】:2013-07-24 15:23:55
【问题描述】:

我想创建一个类型来存储一些通用信息,对于我来说,这个类型是 分子,我存储化学图和分子特性的地方。

data Molecule = Molecule {
     name :: Maybe String,
     graph :: Gr Atom Bond,
     property :: Maybe [Property] -- that's a question
} deriving(Show)

我想用元组表示的属性

type Property a = (String,a)

因为属性可以有任何类型:Float、Int、String 等。


问题是如何形成 Molecule 数据结构,所以我将能够在 Molecule 中收集任意数量的任意类型的属性。如果我这样做了

data Molecule a = Molecule {
     name :: Maybe String,
     graph :: Gr Atom Bond,
     property :: Maybe [Property a]
} deriving(Show)

我必须在创建分子时直接指定一种类型。

【问题讨论】:

  • 这里的问题(总是)是这样的:你想对一个属性做什么?假设您可以在其中放置任何类型。现在你有一个任何东西的清单。您通常如何处理此类列表?

标签: haskell


【解决方案1】:

如果您事先知道一个分子可能具有的一组属性,您可以定义一个 sum 类型:

data Property = Mass Float | CatalogNum Int | Comment String

如果您希望此类型可扩展,您可以使用 Data.Dynamic 作为另一个答案的建议。例如:

data Molecule = Molecule { name :: Maybe String,
                           graph :: Gr Atom Bond,
                           property :: [(String,Dynamic)]
                         } deriving (Show)

mass :: Molecule -> Maybe Float
mass m = case lookup "mass" (property m) of
           Nothing -> Nothing
           Just  i -> fromDynamic i

你也可以去掉“字符串类型”(String,a) 对,比如:

-- in Molecule: 
--   property :: [Dynamic]

data Mass = Mass Float

mass :: Molecule -> Maybe Mass
mass m = ...

这些尝试都没有提供比仅仅解析出 (String,String) 对更多的类型安全性,因为没有办法强制用户创建格式良好的属性的不变量(没有将属性包装在新类型中并隐藏构造函数在另一个模块中,这再次破坏了可扩展性)。

您可能想要的是 Ocaml 风格的多态变体。你可以看看Vinyl,它提供了类型安全的可扩展记录。

顺便说一句,您可能希望摆脱属性列表周围的 Maybe 包装,因为空列表已经编码了没有属性的情况。

【讨论】:

    【解决方案2】:

    您可能想查看Data.Dynamic 以获得伪动态类型解决方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-09-29
      • 2015-08-12
      • 2012-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-23
      相关资源
      最近更新 更多