Haskell通用数据结构

时间:2013-07-24 15:23:55

标签: haskell

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

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 e.t.c.


问题是如何形成分子数据结构,因此我将能够在Molecule中收集任意数量的任何类型的属性。如果我做

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

当我创造一个分子时,我必须直接指定一种类型。

2 个答案:

答案 0 :(得分:3)

如果您事先知道分子可能具有的属性集,则可以定义总和类型:

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包装器,因为空列表已经编码了没有属性的情况。

答案 1 :(得分:0)

您可能希望查看Data.Dynamic的伪动态类型解决方案。