これは、ここでの私のモジュールに関連する質問であり、少し簡略化されています。これは、この前の質問にも関連しています。この質問では、問題を単純化しすぎて、探していた答えが得られませんでした。これがあまり具体的ではないことを願っています。より良いものかどうか考えられる場合は、タイトルを変更してください。
バックグラウンド
私のモジュールは並行chanを使用し、読み取り側と書き込み側に分割されています。多形チャネル「joins」をサポートするために、タイプシノニムが関連付けられた特別なクラスを使用します。
{-# LANGUAGE TypeFamilies #-}
class Sources s where
type Joined s
newJoinedChan :: IO (s, Messages (Joined s)) -- NOT EXPORTED
--output and input sides of channel:
data Messages a -- NOT EXPORTED
data Mailbox a
instance Sources (Mailbox a) where
type Joined (Mailbox a) = a
newJoinedChan = undefined
instance (Sources a, Sources b)=> Sources (a,b) where
type Joined (a,b) = (Joined a, Joined b)
newJoinedChan = undefined
-- and so on for tuples of 3,4,5...
上記のコードを使用すると、次のようなことができます。
example = do
(mb , msgsA) <- newJoinedChan
((mb1, mb2), msgsB) <- newJoinedChan
--say that: msgsA, msgsB :: Messages (Int,Int)
--and: mb :: Mailbox (Int,Int)
-- mb1,mb2 :: Mailbox Int
Behavior
チャネルの「読み取り」端から引き出したメッセージに対して実行できる、と呼ばれる再帰アクションがあります。
newtype Behavior a = Behavior (a -> IO (Behavior a))
runBehaviorOn :: Behavior a -> Messages a -> IO () -- NOT EXPORTED
これにより、またはBehavior (Int,Int)
のいずれかでを実行できるようになります。2番目のケースでは、受け取るタプルの両方が実際には別々のesを経由していました。msgsA
msgsB
Int
Mailbox
spawn
これはすべて、公開された関数でユーザーのために結び付けられています
spawn :: (Sources s) => Behavior (Joined s) -> IO s
...とを呼び出しnewJoinedChan
、runBehaviorOn
入力を返しますSources
。
やりたいこと
Behavior
ユーザーが(タプルだけでなく)任意の製品タイプを作成できるようにしたいので、たとえば、上記Behavior (Pair Int Int)
の例でを実行できますMessages
。GHC.Generics
多形性を維持しながらこれを実行したいのですが、Sources
うまく機能させることができません。
spawn :: (Sources s, Generic (Joined s), Rep (Joined s) ~ ??) => Behavior (Joined s) -> IO s
APIで実際に公開される上記の例の部分はfst
、newJoinedChan
アクションのとBehavior
sであるため、許容可能なソリューションでは、の1つまたはすべてrunBehaviorOn
またはのsnd
を変更できnewJoinedChan
ます。
また、上記のAPIを拡張して、合計(まだ実装されていない)をサポートするようにするBehavior (Either a b)
ので、GHC.Genericsが機能することを期待していました。
質問
上記のAPIを拡張して任意のAPIをサポートする方法はあり
Generic a=> Behavior a
ますか?GHCのジェネリックスを使用していない場合、エンドユーザーの苦痛を最小限に抑えて必要なAPIを取得する他の方法はありますか(つまり、型に派生句を追加するだけです)?例:
Data.Data
?