简体   繁体   English

Haskell通用数据结构

[英]Haskell generic data structure

I want to create a type to store some generic information, as for me, this type is Molecule, where i store chemical graph and molecular properties. 我想创建一个类型来存储一些通用信息,对我来说,这种类型是Molecule,我存储化学图和分子属性。

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

Properties I want to represent as tuple 属性我想表示为元组

type Property a = (String,a)

because a property may have any type: Float, Int, String etc 因为属性可以有任何类型:Float,Int,String等


The question is how to form Molecule data structure, so I will be able to collect any numbers of any types of properties in Molecule. 问题是如何形成分子数据结构,因此我将能够在Molecule中收集任意数量的任何类型的属性。 If I do 如果我做

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

I have to diretly assign one type when I create a molecule. 当我创造一个分子时,我必须直接分配一种类型。

If you know in advance the set of properties a molecule might have, you could define a sum type: 如果您事先知道分子可能具有的属性集,则可以定义总和类型:

data Property = Mass Float | CatalogNum Int | Comment String

If you want this type to be extensible, you could use Data.Dynamic as another answer suggests. 如果您希望此类型是可扩展的,则可以使用Data.Dynamic作为另一个答案建议。 For instance: 例如:

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

You could also get rid of the "stringly-typed" (String,a) pairs, say: 你也可以摆脱“stringly-typed” (String,a)对,比如说:

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

data Mass = Mass Float

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

Neither of these attempts gives much type safety over just parsing out of (String,String) pairs since there is no way to enforce the invariant that the user creates well-formed properties (short of wrapping properties in a new type and hiding the constructors in another module, which again breaks extensibility). 这些尝试都没有提供类型安全性而只是解析出(String,String)对,因为无法强制执行用户创建格式良好的属性的不变量(缺少在新类型中包装属性并隐藏构造函数另一个模块,它再次打破了可扩展性)。

What you might want are Ocaml-style polymorphic variants. 你可能想要的是Ocaml风格的多态变体。 You could look at Vinyl , which provides type-safe extensible records. 您可以查看Vinyl ,它提供类型安全的可扩展记录。

As an aside, you might want to get rid of the Maybe wrapper around the list of properties, since the empty list already encodes the case of no properties. 另外,您可能希望摆脱属性列表周围的Maybe包装器,因为空列表已经编码了没有属性的情况。

您可能希望查看Data.Dynamic以获取psudo动态类型解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM