列挙可能で境界のある型のすべての値を列挙するユーティリティ関数があります。
enumerate :: (Enum a, Bounded a) => [a]
enumerate = [minBound .. maxBound]
および列挙可能な型を整数にマッピングするデータ型:
data Attribute a = Attribute { test :: a -> Int
, vals :: [Int]
, name :: String }
vals
可能なすべての列挙可能な値を表す整数のリストはどこにありますか。たとえば、私が持っていた場合
data Foo = Zero | One | Two deriving (Enum,Bounded)
それならvals
そうでしょう[0,1,2]
。
a
を列挙可能な型にマップする関数と名前を指定するだけで、これらの属性をプログラムで作成できるようにしたいと考えています。このようなもの:
attribute :: (Enum b, Bounded b) => (a -> b) -> String -> Attribute a
attribute f str = Attribute (fromEnum . f) vs str
where
vs = map fromEnum enumerate
enumerate
呼び出しをb
型シグネチャでに接続する方法がないため、これは型チェックしません。だから私はこれができると思った:
vs = map fromEnum $ enumerate :: [b]
しかし、それもコンパイルされません-コンパイラはそれをに名前を変更しb
ますb1
. GADTs 拡張機能を使用して、より賢くしようとしました。
attribute :: (Enum b, Bounded b, b ~ c) => {- ... -}
vs = map fromEnum $ enumerate :: (Enum c,Bounded c) => [c]
ただし、c
は に名前が変更されていc1
ます。
b
の型をパラメーターとして型に含めたくありませんAttribute
(主に、の値が異なる可能性のある属性のリストを格納したいためです。それが、 has typeとhas typeb
の理由です)。test
a -> Int
vals
[Int]
やりたいことを実行できるように、このコードをどのように書くことができますか?