<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>