[Haskell-cafe] best practice for lifting of IO and could lifting
Dimitri DeFigueiredo
defigueiredo at ucdavis.edu
Tue Oct 27 23:25:18 UTC 2015
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.
The Pipe monad transformer augments the base monad with two operations:
- await: gets a result from an upstream pipe
- yield: sends a result to a downstream pipe
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:
getFileContentsLifted :: Producer String IO ()
getFileContentsLifted = withCSVLifted "data.csv" myReadFile
where
myReadFile :: Handle -> Producer String IO ()
myReadFile handle = do
eof <- lift $ hIsEOF handle
unless eof $ do
str <- lift $ hGetLine handle
yield str
myReadFile handle
I then have a simple pipeline that reads each line and prints it twice:
lineDoubler :: Pipe String String IO ()
lineDoubler = forever $ do
s <- await
yield s
yield s
main = do
runEffect $ getFileContentsLifted >-> lineDoubler >-> stdoutLn
The problem as before is that this code does not work with the original
version of withCSV:
withCSV :: FilePath -> (Handle -> IO r) -> IO r
withCSV path action = do
putStrLn "opening file"
h <- openFile path ReadMode
r <- action h
hClose h
putStrLn "file closed"
return r
only with the lifted (i.e. generalized) one.
withCSVLifted :: MonadIO mIO => FilePath -> (Handle -> mIO r) -> mIO r
withCSVLifted path action = do
liftIO $ putStrLn "opening file"
h <- liftIO $ openFile path ReadMode
r <- action h
liftIO $ hClose h
liftIO $ putStrLn "file closed"
return r
And I have the same question: Should I always "generalize" my monadic
actions that take callbacks as parameters?
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.
Dimitri
PS. Full code is here
https://gist.github.com/dimitri-xyz/f1f5bd4c0f7f2bf85379
On 10/26/15 10:47 AM, Kim-Ee Yeoh wrote:
>
> On Mon, Oct 26, 2015 at 11:36 PM, Dimitri DeFigueiredo
> <defigueiredo at ucdavis.edu <mailto:defigueiredo at ucdavis.edu>> wrote:
>
> 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).
>
>
> Is there a way you could introduce just enough complexity to allow
> Oleg another stab?
>
> Also, there's always the fallback of showing your Pipes-based code
> although that library doesn't enjoy universal familiarity.
>
> -- Kim-Ee
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20151027/4692105f/attachment.html>
More information about the Haskell-Cafe
mailing list