pipes
のような型への抽象インターフェイスを定義するために、ライブラリの型クラスを作成していProxy
ます。型クラスは次のようになります。
class ProxyC p where
idT :: (Monad m) => b' -> p a' a b' b m r
(<-<) :: (Monad m)
=> (c' -> p b' b c' c m r)
-> (b' -> p a' a b' b m r)
-> (c' -> p a' a c' c m r)
... -- other methods
Proxy
次の形式のタイプの拡張機能も作成しています。
instance (ProxyC p) => ProxyC (SomeExtension p) where ....
...そして、これらのインスタンスが追加の制約を課すことm
ができるようにしたいMonad
と思います。p a' a b' b m
Monad
a'
a
b'
b
ProxyC
ただし、それをクラスまたはインスタンスの制約としてきれいにエンコードする方法がわかりません。私が現在知っている唯一の解決策は、クラスのメソッドシグネチャでエンコードするようなことです:
(<-<) :: (Monad m, Monad (p b' b c' c m), Monad (p a' a b' b m))
=> (c' -> p b' b c' c m r)
-> (b' -> p a' a b' b m r)
-> (c' -> p a' a c' c m r)
...しかし、よりシンプルでエレガントなソリューションがあることを望んでいました。
編集:次のインスタンスが与えられた場合でも、コンパイラは変数の特定の選択を(Monad (SomeExtension p a' a b' b m))
意味することを推測しないため、最後の解決策でさえ機能しません。(Monad (p a' a b' b m))
instance (Monad (p a b m)) => Monad (SomeExtension p a b m) where ...
編集#2:私が検討している次の解決策は、Monad
クラス内のProxyC
クラスのメソッドを複製することです:
class ProxyC p where
return' :: (Monad m) => r -> p a' a b' b m r
(!>=) :: (Monad m) => ...
...そして、各ProxyC
インスタンスでそれらをインスタンス化します。Monad
メソッドは拡張機能の書き込みのために内部でのみ使用する必要があり、元の型Monad
には下流のユーザー向けの適切なインスタンスがまだあるため、これは私の目的には問題ないようです。Monad
これでできることは、メソッドをインスタンス ライターに公開するだけです。