Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How come `Effect` seals only two in-flows, instead of all the flows?

Here is the diagram of Effect provided in the official tutorial of pipes package.

 type Effect = Proxy X () () X

  Upstream | Downstream
     +---------+
     |         |
 X  <==       <== ()
     |         |
 () ==>       ==> X
     |    |    |
     +----|----+
          v
          r

Since Effect doesn't have any flow of data, I was expecting it to be just Proxy X X X X, sealing all flows. But instead, it allows the two in-flows. Is there a particular reason for that? If I just write what a Effect normally does, with signature Proxy X X X X, it can pass the compiler perfectly fine:

myMonad :: Proxy X X X X IO ()
myMonad = do
    a <- lift $ getLine
    lift $ print a
    return ()

Why can't we run something like this?

like image 780
xzhu Avatar asked Oct 21 '15 21:10

xzhu


1 Answers

You can run myMonad from your example, by just taking the existing definition of runEffect and generalizing its type somewhat:

import Pipes (lift)
import Pipes.Core (closed)
import Pipes.Internal

type Effect' a b = Proxy X a b X

-- Definition copied straight from Pipes.Core, type generalized to Effect'
runEffect' :: Monad m => Effect' a b m r -> m r
runEffect' = go
  where
    go p = case p of
        Request v _ -> closed v
        Respond v _ -> closed v
        M       m   -> m >>= go
        Pure    r   -> return r

eff :: Effect' X X IO ()
eff = do
    a <- lift $ getLine
    lift $ print a
    return ()

main :: IO ()
main = runEffect' eff
like image 181
Cactus Avatar answered Sep 20 '22 05:09

Cactus