<html>
  <head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    Here's a final pipes example then. I don't think there's a way to
    fix the problem as Oleg proposed because pipes are monad
    transformers by design.<br>
    <br>
    The Pipe monad transformer augments the base monad with two
    operations:<br>
    - await: gets a result from an upstream pipe<br>
    - yield: sends a result to a downstream pipe<br>
    <br>
    I have a producer (which is a pipe that can only 'yield') that
    produces the lines of the .CSV file as Strings and returns () when
    done:<br>
    <br>
    <tt>getFileContentsLifted :: Producer String IO ()<br>
      getFileContentsLifted = withCSVLifted "data.csv" myReadFile<br>
          where<br>
              myReadFile :: Handle -> Producer String IO ()<br>
              myReadFile handle = do<br>
                                  eof <- lift $ hIsEOF handle<br>
                                  unless eof $ do<br>
                                      str <- lift $ hGetLine handle<br>
                                      yield str<br>
                                      myReadFile handle<br>
    </tt><br>
    I then have a simple pipeline that reads each line and prints it
    twice:<br>
    <br>
    <tt>lineDoubler :: Pipe String String IO ()<br>
      lineDoubler = forever $ do<br>
                  s <- await<br>
                  yield s<br>
                  yield s<br>
      <br>
      main = do<br>
          runEffect $ getFileContentsLifted >-> lineDoubler
      >-> stdoutLn<br>
    </tt><br>
    The problem as before is that this code does not work with the
    original version of withCSV:<br>
    <tt><br>
    </tt><tt><tt>withCSV :: FilePath -> (Handle -> IO r) -> IO
        r<br>
        withCSV path action = do<br>
            putStrLn "opening file"<br>
            h <- openFile path ReadMode<br>
            r <- action h<br>
            hClose h<br>
            putStrLn "file closed"<br>
            return r<br>
      </tt></tt><br>
    only with the lifted (i.e. generalized) one.<br>
    <br>
    <tt>withCSVLifted :: MonadIO mIO => FilePath -> (Handle ->
      mIO r) -> mIO r<br>
      withCSVLifted path action = do<br>
          liftIO $ putStrLn "opening file"<br>
          h <- liftIO $ openFile path ReadMode<br>
          r <- action h<br>
          liftIO $ hClose h<br>
          liftIO $ putStrLn "file closed"<br>
          return r<br>
    </tt><br>
    And I have the same question: Should I always "generalize" my
    monadic actions that take callbacks as parameters?<br>
    <br>
    I hope this version is still clear. Thanks for everyone for their
    input. I thought this was an easier problem than it now appears to
    be.<br>
    <br>
    Dimitri<br>
    <br>
    PS. Full code is here
    <a class="moz-txt-link-freetext" href="https://gist.github.com/dimitri-xyz/f1f5bd4c0f7f2bf85379">https://gist.github.com/dimitri-xyz/f1f5bd4c0f7f2bf85379</a><br>
    <br>
    <br>
    <div class="moz-cite-prefix">On 10/26/15 10:47 AM, Kim-Ee Yeoh
      wrote:<br>
    </div>
    <blockquote
cite="mid:CAPY+ZdSR7jRn_gV1=WfYOuRpW=wz5no+anQQM78PSQG9XAsFcw@mail.gmail.com"
      type="cite">
      <div dir="ltr">
        <div class="gmail_extra"><br>
          <div class="gmail_quote">On Mon, Oct 26, 2015 at 11:36 PM,
            Dimitri DeFigueiredo <span dir="ltr"><<a
                moz-do-not-send="true"
                href="mailto:defigueiredo@ucdavis.edu" target="_blank"><a class="moz-txt-link-abbreviated" href="mailto:defigueiredo@ucdavis.edu">defigueiredo@ucdavis.edu</a></a>></span>
            wrote:<br>
            <blockquote class="gmail_quote" style="margin:0 0 0
              .8ex;border-left:1px #ccc solid;padding-left:1ex"> I might
              have over simplified the problem by using ReaderT in my
              example. In my original problem this role is played by the
              Pipes library (and instead of using 'ask', I wanted to
              'yield' control to a downstream pipe).</blockquote>
          </div>
          <br>
        </div>
        <div class="gmail_extra">Is there a way you could introduce just
          enough complexity to allow Oleg another stab?<br>
          <br>
        </div>
        <div class="gmail_extra">Also, there's always the fallback of
          showing your Pipes-based code although that library doesn't
          enjoy universal familiarity.<br>
        </div>
        <div class="gmail_extra"><br clear="all">
          <div>
            <div class="gmail_signature">-- Kim-Ee</div>
          </div>
        </div>
      </div>
    </blockquote>
    <br>
  </body>
</html>