4

私のコードには、このクラスに似たものがあります。私の状況では、クラスFooに別のパラメーターとして'を追加することは意味がありません。

class Foo a where
    type FCtx a a' :: Constraint
    type FCtx a a' = ()

    f :: (FCtx a a') => a -> a'

data D b = D b

instance (Integral b) => Foo (D b) where
    -- the next line does not compile because b' does not appear on the LHS
    type FCtx (D b) a' = (a' ~ D b', Integral b') 

    f (D x) = D $ fromIntegral x

のこの特定のインスタンスについては、このように関連付けFooたいと思います。a'この作業を行うために私が思いついた唯一の方法は、「明らかな」タイプの同義語を持つ「ダミー」クラスを追加することです。

class DClass d where
   type DType d

instance DClass (D b) where
    type DType (D b) = b

Fooインスタンスは次のようになります。

instance (Integral b) => Foo (D b) where
    type FCtx (D b) a' = (a' ~ D (DType a'), Integral (DType a'))
    f (D x) = D $ fromIntegral x

問題は、(D b)がbを決定する型の同義語/関数従属性を表現するためだけに、特定のデータ型のクラス全体(およびインスタンス)を作成する必要があったことです。タイプパラメータを常に意味したいので、このクラスの他のインスタンスはありません。DType a'D b

代わりに私がやりたいことは次のようなものです:

type DParam (D b) = b

instance (Integral b) => Foo (D b) where
     type FCtx (D b) a' = (a' ~ D (DParam a'), Integral (DParam a'))
     f (D x) = D $ fromIntegral x

または、型の同義語をまったく使用せずに、この制約を表現するためのより良い方法もあります。これを達成するためだけに、単一のインスタンスと同義の型を持つ(オープン)クラスを作成することを余儀なくされるのはばかげているようです。他の人が私が意図しない新しいインスタンスを作成する可能性があるのは危険です。

少なくとも、「パターン一致型の同義語」をDClass上記のクラス/インスタンスに変換する標準的な方法はないでしょうか。

4

1 に答える 1

5

タイプファミリーを使用して、わずかに軽量化:

type family DParam d :: *
type instance DParam (D b) = b

あなたが今もっとうまくやれるかどうかわからない...

于 2013-01-24T07:53:32.920 に答える