1

私はいくつかの一般的な情報を格納する型を作成したいと思います。私にとっては、この型は Molecule であり、化学グラフと分子特性を格納します。

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)

分子を作成するとき、1 つのタイプを直接指定する必要があります。

4

2 に答える 2

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)「stringly-typed」のペアを取り除くこともできます。

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

data Mass = Mass Float

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

ユーザーが適切な形式のプロパティを作成するという不変条件を強制する方法がないため、これらの試みのどちらも、(String,String)ペアを解析するだけの場合よりも多くの型安全性を提供しません (新しい型でプロパティをラップし、別のモジュールでコンストラクターを非表示にすることを除けば、これも同様です)。拡張性を壊します)。

あなたが望むのは、Ocaml スタイルのポリモーフィック バリアントです。タイプセーフな拡張可能なレコードを提供するVinylを見ることができます。

余談ですがMaybe、空のリストはプロパティがないケースを既にエンコードしているため、プロパティのリストのラッパーを取り除きたい場合があります。

于 2013-07-24T15:57:47.543 に答える
0

疑似動的型付けソリューションについては、Data.Dynamic参照してください。

于 2013-07-24T15:48:00.133 に答える