我想要创建一个类型来存储一些通用信息,对于我来说,这种类型是分子,在这里我存储化学图和分子特性。
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、Stringe.t.c。
问题是如何形成分子数据结构,这样我就能收集分子中任何类型性质的任何数字。如果我做了
data Molecule a = Molecule {
name :: Maybe String,
graph :: Gr Atom Bond,
property :: Maybe [Property a]
} deriving(Show)当我创造一个分子的时候,我必须给出一种类型。
发布于 2013-07-24 15:57:47
如果您事先知道一个分子可能具有的属性集合,您可以定义一个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风格的多态变体。您可以看看乙烯基,它提供了类型安全的可扩展记录。
另外,您可能希望去掉属性列表的Maybe包装器,因为空列表已经对没有属性的情况进行了编码。
发布于 2013-07-24 15:48:00
您可能需要查看Data.Dynamic的psudo动态类型解决方案。
https://stackoverflow.com/questions/17838368
复制相似问题