2010-12-01 4 views
2

Data.MapにはdataCast2が定義されています。 dataCast1のデフォルトはconst Nothingです。 dataCast2は、容易にgcast2と定義される。参考Data.Data - arity 2型コンストラクタのdataCast1を生成する(部分的に特殊化)

:手元

class Typeable a => Data a where 
    dataCast1 :: Typeable1 t => (forall d. Data d => c (t d)) -> Maybe (c a) 
    dataCast2 :: Typeable2 t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a) 
    ... 

gcast1 :: (Typeable1 t, Typeable1 t') => c (t a) -> Maybe (c (t' a)) 
gcast2 :: (Typeable2 t, Typeable2 t') => c (t a b) -> Maybe (c (t' a b)) 

質問はこれです:等Data.Dataのすべて、Data.Typeableを与え、そしてMap、たとえば(定義された、又はされdataCast2ためアリティ2種類のコンストラクタを与え(,) )、この型のコンストラクタの部分的な特殊化のために、一度に1つの特定のコンストラクタに対して、または一般的に、正しいことを行うdataCast1のバージョンを書くことは可能ですか?

直感的には、良い解決策があるはずですが、私の最初のいくつかの試みはクラッシュして焼き付けられました。

+0

これは興味深い問題のように見えますが、もう少し背景が必要だと思います。まず、質問。 「この型のコンストラクタの部分的なアプリケーションに適切なことをしている」ということは、正確にはどういう意味ですか?タイプコンストラクタは、クラス宣言またはインスタンス宣言の先頭に部分的に適用されているように見えますが、AFAIKが完全に適用されている必要がある場所であればどこでもかまいません。 –

+0

@Sean良い点。私はそれを「部分的専門化」と読み替えました。 '未知(c(多分a))'の結果で 'dataCast1'を呼び出すのと同じ方法で、'おそらく(c(Int、a)) 'の結果を持つ' myDataCast1'を呼び出すことができます。 – sclv

答えて

1

私はこれがあなたが望むものかどうかはわかりませんが、そうでない場合はあなたを正しい方向に向けるかもしれません。これは、Data.Typeableライブラリのgcast,gcast1、およびgcast2関数と非常に似たスタイルで書かれています。詳細については、「ソースを読む、Luke」を参照してください。あなたは、例えばfoo

foo :: Typeable d => c (d, a) -> Maybe (c (Int, a)) 
foo = myDataCast1 
+0

が閉じますが、いいえ:-)扱いにくいのは、dataCastが 'Data a => Maybe(c a)'型のものを生成する方法にマッチすることです。つまり、その結果に 'c'以外の型コンストラクタはありません。これがなぜ必要なのかを知るには、 'Data.Generics.Aliases'を試してみて、なぜ' ext1Q'を 'dataCast1'の代わりに' gcast1'で書くのがいいのか考えてみてください。 – sclv

0

このpaperによるdataCast1を実装する方法は、どちらか

dataCast1 f = gcast1 f -- for unuary type constructors 

または

dataCast1 f = Nothing -- for non-unary type constructors 
ようですを書くことができ、この機能を使用する

myDataCast1 :: forall c t d e a.(Typeable d, Typeable e) => c (t d a) -> Maybe (c (t e a)) 
myDataCast1 x = r 
    where 
    r = case typeOf (getArg x) == typeOf (getArg (fromJust r)) of 
      True -> Just $ unsafeCoerce x 
      False -> Nothing 
    getArg :: c (t x a) -> x 
    getArg = undefined 

これはこれを実装する唯一の方法ではないと言われていますが、そうかもしれません。おそらくそれは著者に聞く価値がありますか?私はコア型の問題は、タイプコンストラクタを部分的に適用できないということです。例えば以下は不可能です

data T a b = ... 

instance Typeable a => Data (T Int) where 
    dataCast1 f = ... 

GHCは、十分な型引数にTが適用されていないと不満を持ちます。

私はうまくいくと思います。私たちは新しいタイプを定義します

newtype PairInt a = PairInt (Int, a) deriving Typeable 

instance (Typeable a, Data a) => Data (PairInt a) where 
    dataCast1 f = gcast1 f 

それはかなり迷惑ですが、それは仕事をします。しかし、おそらくそれはあなたが達成しようとしているものに合っていません。

関連する問題