ここで何を求めているのかを正確に伝えるのは難しいです。確かに、特定の type を選択し、Ta を逆シリアルByteString化し、 に格納できAnyNodeます。AnyNodeしかし、それはユーザーにとってあまり良いことではありませんT。制約がなければTypeable、ユーザーは型が何であるかを知ることさえできません (Typeable混乱を招くので、制約を取り除きましょう)。たぶん、あなたが望むのは実存的なものではなく、普遍的なものです。
Serialize2 つのクラスに分割して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、同じ型の別の値に変換できることを意味します. しかし、あなたはそれで何もできません!readsしか生成 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 の戻り値であることに注意してください。showshow :: (∃a. Show a *> a) -> StringReadUnreadread :: String -> (∀a. Read a => a)
では、実存的なものと普遍的なもの、何を求めているのでしょうか? ∀a. (Show a, Read a) => a確かにまたはのようなものを作成できます∃a. (Show a, Read a) *> aが、ここでもあまり役に立ちません。本当の問題は数量詞です。
(私は少し前に別の文脈でこれについて話している質問をしました。)