ここで何を求めているのかを正確に伝えるのは難しいです。確かに、特定の type を選択し、T
a を逆シリアルByteString
化し、 に格納できAnyNode
ます。AnyNode
しかし、それはユーザーにとってあまり良いことではありませんT
。制約がなければTypeable
、ユーザーは型が何であるかを知ることさえできません (Typeable
混乱を招くので、制約を取り除きましょう)。たぶん、あなたが望むのは実存的なものではなく、普遍的なものです。
Serialize
2 つのクラスに分割してRead
、and と呼びShow
、少し単純化します (たとえばread
、失敗しないようにします)。
だから私たちは持っています
class Show a where show :: a -> String
class Read a where read :: String -> a
Show
-able 値の存在コンテナを作成できます。
data ShowEx where
ShowEx :: forall a. Show a => a -> ShowEx
-- non-GADT: data ShowEx = forall a. Show a => ShowEx a
しかし、もちろんShowEx
は と同形String
なので、これを指している点はあまりありません。Read
しかし、 is の存在論的意味はさらに少ないことに注意してください:
data ReadEx where
ReadEx :: forall a. Read a => a -> ReadEx
-- non-GADT: data ReadEx = forall a. Read a => ReadEx a
私があなたに与えるとき、ReadEx
つまり∃a. Read a *> a
、それはあなたが何らかの型の値を持っていて、その型が何であるかはわかりませんがString
、同じ型の別の値に変換できることを意味します. しかし、あなたはそれで何もできません!read
sしか生成 a
しませんが、何が何であるかがわからない場合は、何の役にも立ちませんa
。
あなたが望むかもしれないRead
のは、呼び出し元が選択できるタイプ、つまりユニバーサルです。何かのようなもの
newtype ReadUn where
ReadUn :: (forall a. Read a => a) -> ReadUn
-- non-GADT: newtype ReadUn = ReadUn (forall a. Read a => a)
(のようReadEx
に、あなたは作ることができますShowUn
-つまり∀a. Show a => a
-そしてそれは同じように役に立たないでしょう。)
は本質的に --ie --ShowEx
の引数であり、本質的に --ie の戻り値であることに注意してください。show
show :: (∃a. Show a *> a) -> String
ReadUn
read
read :: String -> (∀a. Read a => a)
では、実存的なものと普遍的なもの、何を求めているのでしょうか? ∀a. (Show a, Read a) => a
確かにまたはのようなものを作成できます∃a. (Show a, Read a) *> a
が、ここでもあまり役に立ちません。本当の問題は数量詞です。
(私は少し前に別の文脈でこれについて話している質問をしました。)