2006-09-16 [長年日記]

[Haskell] Existential QuantificationPolymorphic Componentsの違い

Existential Quantificationは、

data Ex = forall a. Num a => Ex a

のような形式で、Polymorphic Componentsは、

data Po = Po (forall a. Num a => a)

のような形式です。

Exの方はデータコンストラクタを呼び出す時点で具体的な型が確定するので、

ex = Ex (1 :: Int)

のようにできますが、Poの方はNumのインスタンスであるようなaでなくてはいけないので、

po = Po (1 :: Int)

とはできず、無理にやるならば

po = Po (fromIntegral (1 :: Int))

のようにする必要があります。

逆に、Exのデータコンストラクタに渡された引数の方は具象型な上にデータコンストラクタから出たら失われてしまうので、

addEx :: Ex -> Ex -> Ex
addEx (Ex x) (Ex y) = Ex (x + y)

のようには書けません(一番目の引数がEx (1 :: Int)として構築されて、二番目の引数がEx (1 :: Float)として構築されていたら(+)が呼び出せないので)。Poの方は常にNum aな引数を取るので、

addPo :: Po -> Po -> Po
addPo (Po x) (Po y) = Po (x + y)

のようにすることができます((+)の型がNum a => a -> a -> aなので)。

しかし、Poと以下のPo2の違いが良くわかりません…

data Num a => Po2 a = Po2 a

addPo2 :: Num a => Po2 a -> Po2 a -> Po2 a
addPo2 (Po2 x) (Po2 y) = Po2 (x + y)

具体的な型がPoになるかPo2 aになるかという違いはあるものの、同じことができるような気がします。データコンストラクタが複数ある場合には別ですけど。

[]