型クラスの制約は本質的に暗黙のパラメータと考えることができます-つまり、
Foo a => b
なので
FooDict a -> b
ここFooDict a
で、はクラスで定義されたメソッドのディクショナリですFoo
。たとえばEqDict
、次のレコードになります。
data EqDict a = EqDict { equal :: a -> a -> Bool, notEqual :: a -> a -> Bool }
違いは、各タイプで各ディクショナリの値は1つだけであり(MPTCに対して適切に一般化)、GHCがその値を入力することです。
これを念頭に置いて、私たちはあなたの署名に戻ることができます。
type FooT m a = (MyMonad m) => ListT m a
foo :: MyType a -> MyOtherType a -> FooT m a
に拡大
foo :: MyType a -> MyOtherType a -> (MyMonad m => ListT m a)
辞書の解釈を使用する
foo :: MyType a -> MyOtherType a -> MyMonadDict m -> ListT m a
これは、引数を次のように並べ替えることと同等です。
foo :: MyMonadDict m -> MyType a -> MyOtherType a -> ListT m a
これは、辞書変換の逆と同等です。
foo :: (MyMonad m) => MyType a -> MyOtherType a -> ListT m a
それはあなたが探していたものです。
ただし、他の例では、そのようには機能しません。
type Bar a b = (Something a, SomethingElse b) => NotAsBar a b
bar :: Bar a b -> InsertTypeHere
に拡大
bar :: ((Something a, SomethingElse b) => NotAsBar a b) -> InsertTypeHere
これらの変数は、依然としてトップレベルで定量化されています(つまり、
bar :: forall a b. ((Something a, SomethingElse b) => NotAsBar a b) -> InsertTypeHere
)、あなたはbar
の署名でそれらを明示的に言及したので、しかし私たちが辞書変換を行うとき
bar :: (SomethingDict a -> SomethingElseDict b -> NotAsBar a b) -> InsertTypeHere
これは同等ではないことがわかります
bar :: SomethingDict a -> SomethingElseDict b -> NotAsBar a b -> InsertTypeHere
それはあなたが望むものを生み出すでしょう。
型クラス制約が定量化のポイントとは異なる場所で使用される現実的な例を思い付くのはかなり難しいです-私は実際にそれを見たことがありません-それで、それが起こっていることを示すためだけに非現実的な例があります:
sillyEq :: forall a. ((Eq a => Bool) -> Bool) -> a -> a -> Bool
sillyEq f x y = f (x == y)
==
引数を渡していないときに使用しようとするとどうなるかとは対照的f
です。
sillyEq' :: forall a. ((Eq a => Bool) -> Bool) -> a -> a -> Bool
sillyEq' f x y = f (x == y) || x == y
エラーのインスタンスはありませんEq a
。
(x == y)
insillyEq
はからそのdictEq
を取得しf
ます; その辞書形式は次のとおりです。
sillyEq :: forall a. ((EqDict a -> Bool) -> Bool) -> a -> a -> Bool
sillyEq f x y = f (\eqdict -> equal eqdict x y)
少し後退すると、ここであなたが恐れている方法は苦痛になると思います-コンテキストを定量化するために何かを使用したいだけだと思います。コンテキストは「使用される関数シグネチャ」として定義されます。 "。その概念には単純なセマンティクスはありません。セットの関数と考えることができるはずですBar
。引数として2つのセットを取り、別のセットを返します。あなたが達成しようとしている用途のためにそのような機能があるとは思わない。
コンテキストを短縮する限り、ConstraintKinds
制約の同義語を作成できる拡張機能を利用できる可能性があるため、少なくとも次のように言うことができます。
type Bars a = (Something a, SomethingElse a)
取得するため
bar :: Bars a => Bar a b -> InsertTypeHere
しかし、あなたが望むことはまだ可能かもしれません-あなたの名前は私が言うのに十分な説明ではありません。型変数を抽象化する2つの方法である、存在記号と全称記号を調べることをお勧めします。
話の教訓:これらの引数がコンパイラーによって自動的に入力されることを除いて、それ=>
は同じことを覚えておいてください。そして、明確に定義された数学的意味で型を定義しようとしていることを確認してください。->