As far as I know, do
blocks in Haskell are just some kind of syntactic sugar for monadic bind operators. For example, one could convert
main = do f <- readFile "foo.txt"
print f
print "Finished"
to
main = readFile "foo.txt" >>= print >> print "Finished"
Can all do
blocks be converted to bind syntax? What about, for example, this block where f
is used multiple times:
main = do f <- readFile "foo.txt"
print $ "prefix " ++ f
print $ f ++ " postfix"
Assuming we are in the IO monad, it is not possible to simply execute the readFile
computation twice. How can this example (if possible at all) expressed using only bind syntax?
I think using Control.Monad
is no solution, because it internally uses do
blocks.
I think it it's possible to express this using arrows (using &&&
) -- maybe this is a case where only arrows can be used as a generalization of monads?
Note that this question is not about the special examples above but about the general case of the result of a computation being used multiple times in monadic expressions like print
.
Control.Applicative
has a bunch of operators you can use to mess with stuff of typem a
, then you can>>=
to the output. Usually that's much prettier. Sometimes point free isn't prettier at all; we could writemain = readFile "foo.txt" >>= flip mapM_ [("prefix" ++), (++ "postfix")] . (print .) . flip id
but that wouldn't be very clear. – JohnathanjohnathonforM_
instead offlip mapM_
? – DumuziControl.Monad
. Trouble with that is that if you don't importControl.Monad
, you miss the lovely(>=>) :: Monad m => (a->m b) -> (b->m c) -> (a -> m c)
. – Johnathanjohnathon