##これがダメなのはナゼ?
#derivingを除去すればコンパイルは通るけど、その場合、Dデータを構築する方法ってどうやればいいんでしょう?
#-- when remove deriving, success to compile, but couldn't construct D data.
*Test> :t D (X "Hello") 123 (X "aaa")
<interactive>:1:20:
Could not deduce (a ~ X)
from the context (Show a, Z a)
bound by a type expected by the context: (Show a, Z a) => a
at <interactive>:1:1-27
`a' is a rigid type variable bound by
a type expected by the context: (Show a, Z a) => a
at <interactive>:1:1
In the return type of a call of `X'
In the third argument of `D', namely `(X "aaa")'
In the expression: D (X "Hello") 123 (X "aaa")
*Test>
#GADTsまたはExistentialQuantificationを使えばインスタンス化できることは分った。
#ただし、D (X "Hello") 123 (X "world")ならそのままでもOKだけど、
#D (X "Hello") 123 456はダメで、D (X "Hello") 123 (456::Y)と型を指定すればいける。
#これはこれでなんでなんだ?という疑問が。
#zはアクセサとしても機能しないのね。。。
#*Test> :t z
<interactive>:1:1:
Cannot use record selector `z' as a function due to escaped type variables
Probable fix: use pattern-matching syntax instead
In the expression: z
*Test>
#ちなみに:t zでエラーになるのは以下のコード
##456というリテラルだけではIntかどうか確定しないから、とか? zがアクセサとして使えないのは、まあ、型が決まらないから仕方ないような (「決まらない」って言い方が正しいかどうか知らないけど… D -> Z a になっちゃってaが何かがコンパイル時にはわからない?)
#コンパイル時にわからないっていうのも変か。正しい言い方は知らないんだけど、コンパイラは困るだろうな、という感じは何となくする。
#前者の方はShowクラスとZクラスの制約を満たすすべてのaである値が必要なので、X "world" :: Xとか456 :: Yでは型検査で弾かれます。どういう値が条件を満たすかというと、型クラスZにメンバーを追加すればうまくいきます。
##後者は(もし型が表示されるとしたら)z :: D -> (exists a. (Show a, Z a) => a) となって「あるShowクラスとZクラスの制約を満たすa型」がなんなのか確定できないのでzは関数として使えません。でもえらーメッセージにあるとおり、パターンマッチでは使えるので、Showくらすのメソッドや(あれば)Zクラスのメソッドを通してなら使えます。
###うーん、なんとなくきわどい部分なのは分かるんだけど。
#ちょっと読んでみます。