これは、別の質問に対するガブリエルの回答と密接に関連しています。|||
関数 fromのようなものをArrowChoice
(Proxy
ライブラリからpipes
) に対して提供する関数を作成しました。これはパターン マッチし、5 つの相互再帰関数を持ちます。Pipes.Core
パターン マッチングの代わりに関数 from を使用する代替実装を見つけたいと思います。
left
私は最初に他の答えの実装を適応させようとしました。次のようになります。
newtype Edge m r a b = Edge { unEdge :: a -> Pipe a b m r }
instance (Monad m) => ArrowChoice (Edge m r) where
left (Edge k) = Edge (bef >=> (up \>\ (k />/ dn)))
where
bef x = case x of
Left b -> return b
Right d -> do
_ <- respond (Right d)
x2 <- request ()
bef x2
up () = do
x <- request ()
bef x
dn c = respond (Left c)
ただし、この実装は上流と下流が同じであることに依存しており、それをさらに一般化する方法がわかりませんでした。私が得ることができた最も近いものは次のとおりです。
proxyLeft :: Monad m
=> (a -> Pipes.Proxy y a y b m r)
-> Either a x
-> Pipes.Proxy y (Either a x) y (Either b x) m r
proxyLeft k = bef >=> (up \>\ (k />/ dn))
where
bef x = case x of
Left b -> return b
Right d -> do
a <- respond (Right d)
x2 <- request a
bef x2
up a = do
x <- request a
bef x
dn c = respond (Left c)
の変種のコード スニペット|||
はかなり長いので、何らかの方法でこれを実行できるという証拠として提供しているだけです。関数の名前はdownstreamOr
. 他のすべての関数は、相互に再帰的なヘルパー関数です。
downstreamOr ::
Monad m
=> (b' -> Pipes.Proxy a' a b' b m r)
-> (c' -> Pipes.Proxy a' a c' b m r)
-> Either b' c'
-> Pipes.Proxy a' a (Either b' c') b m r
downstreamOr f g e = case e of
Left b' -> case f b' of
Pipes.Request a' k -> Pipes.Request a' (downstreamOrLeft k g)
Pipes.Respond b k -> Pipes.Respond b (downstreamOr k g)
Pipes.M m -> Pipes.M $ m >>= \p -> return $ downstreamLeftM p g
Pipes.Pure r -> Pipes.Pure r
Right c' -> case g c' of
Pipes.Request a' k -> Pipes.Request a' (downstreamOrRight f k)
Pipes.Respond b k -> Pipes.Respond b (downstreamOr f k)
Pipes.M m -> Pipes.M $ m >>= \p -> return $ downstreamRightM f p
Pipes.Pure r -> Pipes.Pure r
downstreamOrLeft ::
Monad m
=> (a -> Pipes.Proxy a' a b' b m r)
-> (c' -> Pipes.Proxy a' a c' b m r)
-> a
-> Pipes.Proxy a' a (Either b' c') b m r
downstreamOrLeft f g a = case f a of
Pipes.Request a' k -> Pipes.Request a' (downstreamOrLeft k g)
Pipes.Respond b k -> Pipes.Respond b (downstreamOr k g)
Pipes.M m -> Pipes.M $ m >>= \p -> return $ downstreamLeftM p g
Pipes.Pure r -> Pipes.Pure r
downstreamOrRight ::
Monad m
=> (b' -> Pipes.Proxy a' a b' b m r)
-> (a -> Pipes.Proxy a' a c' b m r)
-> a
-> Pipes.Proxy a' a (Either b' c') b m r
downstreamOrRight f g a = case g a of
Pipes.Request a' k -> Pipes.Request a' (downstreamOrRight f k)
Pipes.Respond b k -> Pipes.Respond b (downstreamOr f k)
Pipes.M m -> Pipes.M $ m >>= \p -> return $ downstreamRightM f p
Pipes.Pure r -> Pipes.Pure r
downstreamLeftM ::
Monad m
=> Pipes.Proxy a' a b' b m r
-> (c' -> Pipes.Proxy a' a c' b m r)
-> Pipes.Proxy a' a (Either b' c') b m r
downstreamLeftM p g = case p of
Pipes.Pure r -> Pipes.Pure r
Pipes.Request a' k -> Pipes.Request a' (downstreamOrLeft k g)
Pipes.Respond b k -> Pipes.Respond b (downstreamOr k g)
Pipes.M m -> Pipes.M $ m >>= \p -> return $ downstreamLeftM p g
downstreamRightM ::
Monad m
=> (b' -> Pipes.Proxy a' a b' b m r)
-> Pipes.Proxy a' a c' b m r
-> Pipes.Proxy a' a (Either b' c') b m r
downstreamRightM f p = case p of
Pipes.Pure r -> Pipes.Pure r
Pipes.Respond a' k -> Pipes.Respond a' (downstreamOr f k)
Pipes.Request a' k -> Pipes.Request a' (downstreamOrRight f k)
Pipes.M m -> Pipes.M $ m >>= \p -> return $ downstreamRightM f p
これらのいずれかがパターン マッチングなしでどのように実装できるかを確認すると役に立ちます。ありがとうございます。何か明確にできることがあればお知らせください。