2017-02-23 1 views
4

Es gibt einen archivierten Thread auf reddit, der besagt, dass im Wesentlichen Leitung/Rohre nicht Pfeile sein können Pfeile b/c müssen synchron sein. Der Thread ist hier verknüpft https://www.reddit.com/r/haskell/comments/rq1q5/conduitssinks_and_refactoring_arrows/Warum kann Conduit und Pipe keine Arrow-Instanz haben?

Ich sehe nicht, wo die "synchronen" kommen, da das nicht Teil der Definition von Pfeilen ist. Außerdem stieß ich auf dieses Projekt auf github https://github.com/cmahon/interactive-brokers, das Rohre ausdrücklich als Pfeile behandelt. Ich paste die Instanz def hier für Ihre Bequemlichkeit. Was fehlt mir hier?

-- The code in this module was provided by Gabriel Gonzalez 

{-# LANGUAGE RankNTypes #-} 

module Pipes.Edge where 

import   Control.Arrow 
import   Control.Category (Category((.), id)) 
import   Control.Monad ((>=>)) 
import   Control.Monad.Trans.State.Strict (get, put) 
import   Pipes 
import   Pipes.Core (request, respond, (\>\), (/>/), push, (>~>)) 
import   Pipes.Internal (unsafeHoist) 
import   Pipes.Lift (evalStateP) 
import   Prelude hiding ((.), id) 

newtype Edge m r a b = Edge { unEdge :: a -> Pipe a b m r } 

instance (Monad m) => Category (Edge m r) where 
    id = Edge push 
    (Edge p2) . (Edge p1) = Edge (p1 >~> p2) 

instance (Monad m) => Arrow (Edge m r) where 
    arr f = Edge (push />/ respond . f) 
    first (Edge p) = Edge $ \(b, d) -> 
     evalStateP d $ (up \>\ unsafeHoist lift . p />/ dn) b 
     where 
     up() = do 
      (b, d) <- request() 
      lift $ put d 
      return b 
     dn c = do 
      d <- lift get 
      respond (c, d) 

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) 

runEdge :: (Monad m) => Edge m r a b -> Pipe a b m r 
runEdge e = await >>= unEdge e 
+0

erfüllt dies 'arr (f >>> g) = arr f >>> arr g? Ich vermute, dass es nicht, aber ich bin nicht sicher – hao

+0

Dies wird durch die Kategorie Axiom induziert, nicht wahr? – user2812201

+0

[Diese Nachricht von Gabriel Gonzalez] (https://groups.google.com/d/msg/haskell-pipes/H6YdVhyNksk/xr4NAPHzT2UJ) enthält einige zusätzliche Kommentare zu den Instanzen für Push-basierte Pipes, die Sie angegeben haben. – duplode

Antwort

4

Betrachten Sie dieses Rohr: yield '*' :: Pipe x Char IO(). Wir könnten es in einen NewType-Adapter wie newtype PipeArrow a b = PipeArrow { getPipeArrow :: Pipe a b IO() } einpacken und versuchen, dort die Arrow Instanz zu definieren.

Kaufen, wie man eine first :: PipeArrow b c -> PipeArrow (b, d) (c, d) schreibt, die auf yield '*' arbeitet? Die Pipe wartet nie auf einen Wert von Upstream. Wir müssten ein d aus der Luft produzieren, um die '*' zu begleiten.

Rohre erfüllen die meisten Gesetze für Pfeile (und für ArrowChoice) aber first kann nicht in einer rechtmäßigen Weise implementiert werden.

Der von Ihnen gepostete Code definiert Arrow nicht für Pipe, sondern für eine Funktion, die einen Wert von Upstream nimmt und eine Pipe zurückgibt.

+2

A [Gegenstück] (https://www.paolocapriotti.com/blog/2012/02/04/monoidal-instances-for-pipes/) zu dieser feinen Antwort. – duplode

Verwandte Themen