I'm new to haskell, and i read through and digested Learn You A Haskell For Great Good, trying out a couple of things along the way. For my first project i wanted to try the classic: FizzBuzz. So i came up with the following code:
import System.IO
fizzBuzz :: (Integral a) => a -> String
fizzBuzz num
| fizz && buzz = "FizzBuzz"
| fizz = "Fizz"
| buzz = "Buzz"
| otherwise = show num
where fizz = num `mod` 3 == 0
buzz = num `mod` 5 == 0
main = print $ map fizzBuzz [1..100]
Worked great, except i got a rather dense looking list that was hard to read. So i tried this main function instead:
main = map putStrLn $ map fizzBuzz [1..100]
And that gives me the error Couldn't match expected type 'IO t' against inferred type '[IO ()]'. I tried half a dozen things and none of it seemed to help. What's the proper way to do what i'm trying to do?
map :: (a -> b) -> [a] -> [b]
putStrLn :: Show a => a -> IO ()
map putStrLn :: Show a => [a] -> [IO ()]
You've got a list of IO () actions.
main :: IO ()
You need to join them into a single IO () action.
What you want to do is to perform each of those IO () actions in sequence/sequence_:
sequence :: Monad m => [m a] -> m [a]
sequence_ :: Monad m => [m a] -> m ()
For convenience, mapM/mapM_ will map a function over a list and sequence the resulting monadic results.
mapM :: Monad m => (a -> m b) -> [a] -> m [b]
mapM_ :: Monad m => (a -> m b) -> [a] -> m ()
So your fixed code would look like this:
main = mapM_ putStrLn $ map fizzBuzz [1..100]
Although I'd probably write it like this:
main = mapM_ (putStrLn . fizzBuzz) [1..100]
Or even this:
main = putStr $ unlines $ map fizzBuzz [1..100]
Let's write our own sequence. What do we want it to do?
sequence [] = return []
sequence (m:ms) = do
x <- m
xs <- sequence ms
return $ x:xs
If there's nothing left in the list, return (inject into the monad) an empty list of results.
Otherwise, within the monad,
Bind (for the IO monad, this means execute) the first result.
sequence the rest of the list; bind that list of results.
Return a cons of the first result and the list of other results.
GHC's library uses something more like foldr (liftM2 (:)) (return []) but that's harder to explain to a newcomer; for now, just take my word that they're equivalent.
sequence_ is easier, since it doesn't bother keeping track of the results. GHC's library implements it as sequence_ ms = foldr (>>) (return ()) ms. Let's just expand the definition of foldr:
sequence [a, b, c, d]
= foldr (>>) (return ()) [a, b, c, d]
= a >> (b >> (c >> (d >> return ())))
In other words, "do a, discard the result; do b; discard the result, … finally, return ()".
mapM f xs = sequence $ map f xs
mapM_ f xs = sequence_ $ map f xs
On the other hand, you don't even need to know monads at all with the alternate unlines solution.
What does unlines do? Well, lines "a\nb\nc\nd\n" = ["a", "b", "c", "d"], so of course unlines ["a", "b", "c", "d"] = "a\nb\nc\nd\n".
unlines $ map fizzBuzz [1..100] = unlines ["1", "2", "Fizz", ..] = "1\n2\nFizz\n..." and off it goes to putStr. Thanks to the magic of Haskell's laziness, the full string never needs to be constructed in memory, so this will happily go to [1..1000000] or higher :)
Related
I wrote a recursive algorithm using a list comprehension to perform the recursion. I thought my code was clear and easy to read, and the results it produced were correct.
However, I found it difficult to understand the performance of my code on certain inputs. I thought it would be useful to use the Writer monad to put some logging into my code.
I found it quite difficult to convert my non-monadic code to monadic. Eventually I got it to compile and run correctly, but the monadic code is much less understandable than the original.
The original problem is too complex to explain here, so I have written a toy example that shows the non-monadic and monadic approaches, but doesn't actually calculate anything useful!
So my question is: is there a better way to write the function fMonadic, such that it is more readable?
import Control.Monad (forM)
import Control.Monad.Writer (Writer, runWriter, tell)
fun :: Int -> [[Int]] -> [[Int]]
fun a b = map (map (a +)) b
fNonMonadic :: [[Int]] -> [[Int]]
fNonMonadic [] = [[]]
fNonMonadic (first : rest) =
[ first ++ s
| e <- first
, s <- fNonMonadic $ fun e rest]
fMonadic :: [[Int]] -> Writer [String] [[Int]]
fMonadic [] = do
tell ["base case"]
return [[]]
fMonadic (first : rest) =
fmap concat . forM first $ \ e -> do
tell ["recursive case " ++ show e]
fmap (map (first ++)) $ fMonadic $ fun e rest
main = do
let arg = [[0, 1], [20, 30], [400, 500]]
print $ fNonMonadic arg
let (a, b) = runWriter $ fMonadic arg
print a
mapM_ putStrLn b
It is often awkward to equip pure Haskell functions, which are structured in an algebraic, highly branched tree manner, with a monadic feature such as logging, which requires a more “imperative” structure. However, sometimes it is actually quite natural to write even pure computations using monadic combinators, and yours is in fact one of these. Namely, the list comprehension that's at the heart of fNonMonadic is already basically using the list monad; it can be written thus:
type ListM = [] -- Just to distinguish where I use list as a monad
fNonMonadic :: [[Int]] -> ListM [Int]
fNonMonadic [] = return []
fNonMonadic (first : rest) = do
e <- first
s <- fNonMonadic $ fun e rest
return $ first ++ s
Starting from that, it is much easier to add the writer functionality, by using it as the base of a monad transformer stack. The list must then be used in transformer shape, too:
import Control.Monad.Trans.List
fMonTrafo :: [[Int]] -> ListT (Writer [String]) [Int]
fMonTrafo [] = do
lift $ tell ["base case"]
return []
fMonTrafo (first : rest) = do
e <- ListT $ pure first
lift $ tell ["recursive case " ++ show e]
s <- fMonTrafo $ fun e rest
return $ first ++ s
You may notice that the documentation of ListT warns that the base monad should be commutative, which Writer actually isn't – the order of log entries may get messed up. I don't know if this matters here. If yes, check out the alternative implementation suggested by Daniel Wagner.
I looked at several alternatives to Control.Monad.Trans.List, and soon settled on module ListT from Volkov's list-t package.
This gives the same result as my ugly fMonadic function, but more readable code. It also works correctly, and leads to readable code, in the real problem I want to solve.
In the real problem, the ListT-based code runs slightly more slowly than the ugly code, but the difference isn't enough to matter.
Many thanks again for leftaroundabout's help with this.
For reference, here is the revised version of the toy example, doing the computation the three different ways and showing that the answer is the same:
import Control.Monad (forM)
import ListT (ListT, fromFoldable, toList)
import Control.Monad.Writer (Writer, lift, runWriter, tell)
fun :: Int -> [[Int]] -> [[Int]]
fun a b = map (map (a +)) b
fNonMonadic :: [[Int]] -> [[Int]]
fNonMonadic [] = [[]]
fNonMonadic (first : rest) = do
e <- first
s <- fNonMonadic $ fun e rest
return $ first ++ s
-- The above do notation means the same as this list comprehension:
-- [ first ++ s
-- | e <- first
-- , s <- fNonMonadic $ fun e rest]
fMonadic :: [[Int]] -> Writer [String] [[Int]]
fMonadic [] = do
tell ["base case"]
return [[]]
fMonadic (first : rest) =
fmap concat . forM first $ \ e -> do
tell ["recursive case " ++ show e]
fmap (map (first ++)) $ fMonadic $ fun e rest
fMonTrafo :: [[Int]] -> ListT (Writer [String]) [Int]
fMonTrafo [] = do
lift $ tell ["base case"]
return []
fMonTrafo (first : rest) = do
e <- fromFoldable first
lift $ tell ["recursive case " ++ show e]
s <- fMonTrafo $ fun e rest
return $ first ++ s
main = do
let arg = [[0, 1], [20, 30], [400, 500]]
let x = fNonMonadic arg
print x
let (a, b) = runWriter $ fMonadic arg
print a
mapM_ putStrLn b
let (c, d) = runWriter $ toList $ fMonTrafo arg
print c
mapM_ putStrLn d
putStrLn $ if x == a then "fNonMonadic == fMonadic" else error ""
putStrLn $ if x == c then "fNonMonadic == fMonTrafo" else error ""
putStrLn $ if b == d then "fMonadic log == fMonTrafo log" else error ""
Suppose the code
f :: IO [Int]
f = f >>= return . (0 :)
g :: IO [Int]
g = f >>= return . take 3
When I run g in ghci, it cause stackoverflow. But I was thinking maybe it could be evaluated lazily and produce [0, 0, 0] wrapped in IO. I suspect IO is to blame here, but I really have no idea. Obviously the following works:
f' :: [Int]
f' = 0 : f'
g' :: [Int]
g' = take 3 f'
Edit: In fact I am not interested in having such a simple function f, original code looked more along the lines:
h :: a -> IO [Either b c]
h a = do
(r, a') <- h' a
case r of
x#(Left _) -> h a' >>= return . (x :)
y#(Right _) -> return [y]
h' :: IO (Either b c, a)
-- something non trivial
main :: IO ()
main = mapM_ print . take 3 =<< h a
h does some IO computations and stores invalid (Left) responses in a list until a valid response (Right) is produced. The attempt is to construct the list lazily even though we are in the IO monad. So that someone reading the result of h can start consuming the list even before it is complete (because it may even be infinite). And if the one reading the results cares only for the first 3 entries no matter what, the rest of the list does not even have to be constructed. And I am getting the feeling that this will not be possible :/.
Yes, IO is to blame here. >>= for IO is strict in the "state of the world". If you write m >>= h, you'll get an action that first performs the action m, then applies h to the result, and finally performs the action h yields. It doesn't matter that your f action doesn't "do anything"; it has to be performed anyway. Thus you end up in an infinite loop starting the f action over and over.
Thankfully, there is a way around this, because IO is an instance of MonadFix. You can "magically" access the result of an IO action from within that action. Critically, that access must be sufficiently lazy, or you'll throw yourself into an infinite loop.
import Control.Monad.Fix
import Data.Functor ((<$>))
f :: IO [Int]
f = mfix (\xs -> return (0 : xs))
-- This `g` is just like yours, but prettier IMO
g :: IO [Int]
g = take 3 <$> f
There's even a bit of syntactic sugar in GHC for this letting you use do notation with the rec keyword or mdo notation.
{-# LANGUAGE RecursiveDo #-}
f' :: IO [Int]
f' = do
rec res <- (0:) <$> (return res :: IO [Int])
return res
f'' :: IO [Int]
f'' = mdo
res <- f'
return (0 : res)
For more interesting examples of ways to use MonadFix, see the Haskell Wiki.
It sounds like you want a monad that mixes the capabilities of lists and IO. Luckily, that's just what ListT is for. Here's your example in that form, with an h' that computes the Collatz sequence and asks the user how they feel about each element in the sequence (I couldn't really think of anything convincing that fit the shape of your outline).
import Control.Monad.IO.Class
import qualified ListT as L
h :: Int -> L.ListT IO (Either String ())
h a = do
(r, a') <- liftIO (h' a)
case r of
x#(Left _) -> L.cons x (h a')
y#(Right _) -> return y
h' :: Int -> IO (Either String (), Int)
h' 1 = return (Right (), 1)
h' n = do
putStrLn $ "Say something about " ++ show n
s <- getLine
return (Left s, if even n then n `div` 2 else 3*n + 1)
main = readLn >>= L.traverse_ print . L.take 3 . h
Here's how it looks in ghci:
> main
2
Say something about 2
small
Left "small"
Right ()
> main
3
Say something about 3
prime
Left "prime"
Say something about 10
not prime
Left "not prime"
Say something about 5
fiver
Left "fiver"
I suppose modern approaches would use pipes or conduits or iteratees or something, but I don't know enough about them to talk about the tradeoffs compared to ListT.
I'm not sure if this is an appropriate usage, but unsafeInterleaveIO would get you the behavior you're asking for, by deferring the IO actions of f until the value inside of f is asked for:
module Tmp where
import System.IO.Unsafe (unsafeInterleaveIO)
f :: IO [Int]
f = unsafeInterleaveIO f >>= return . (0 :)
g :: IO [Int]
g = f >>= return . take 3
*Tmp> g
[0,0,0]
List comprehension is very easy to understand. Look at h in the following definition. It uses pure_xs of type [Int], and pure_f of type Int -> String, using both in the list comprehension.
pure_xs :: [Int]
pure_xs = [1,2,3]
pure_f :: Int -> String
pure_f a = show a
h :: [(Int,Char)]
h = [(a,b) | a <- pure_xs, b <- pure_f a]
-- h => [(4,'4'),(5,'5'),(6,'6')]
Great. Now take two slightly different expressions, monadic_f and monadic_xs. I would like to construct g using list comprehensions, to look as similar to h as possible. I have a feeling that a solution will involve generating a sequence of IO actions, and using sequence to generate a list of type [(Int,Char)] in the IO monad.
monadic_xs :: IO [Int]
monadic_xs = return [1,2,3]
monadic_f :: Int -> IO String
monadic_f a = return (show a)
g :: IO [(Int,Char)]
g = undefined -- how to make `g` function look
-- as similar to `h` function as possible, i.e. using list comprehension?
-- g => IO [(4,'4'),(5,'5'),(6,'6')]
The natural way to write this would be
do xs <- monadic_xs
ys <- mapM monadic_f xs
return (zip xs ys)
But we can't translate that naturally into a list comprehension because we need the (>>=) binds in there to extract the monadic values. Monad transformers would be an avenue to interweave these effects. Let's examine the transformers ListT monad transformer — even though it's not actually a monad transformer.
newtype ListT m a = ListT { runListT :: m [a] }
listT_xs :: ListT IO Int
listT_xs = ListT monadic_xs
listT_f :: Int -> ListT IO String
liftT_f = ListT . fmap return . monadic_f
>>> runListT $ do { x <- listT_xs; str <- listT_f x; return (x, str) }
[(1,"1"),(2,"2"),(3,"3")]
So that appears to work and we can turn on MonadComprehensions to write it in a list comprehension format.
>>> runListT [ (x, str) | x <- listT_xs, str <- listT_f x ]
[(1,"1"),(2,"2"),(3,"3")]
That's about as similar to the result you get with the pure version as I can think of, but it has a few dangerous flaws. First, we're using ListT which may be unintuitive due to it breaking the monad transformer laws, and, second, we're using only a tiny fraction of the list monadic effect---normally list will take the cartesian product, not the zip.
listT_g :: Int -> ListT IO String
listT_g = ListT . fmap (replicate 3) . monadic_f
>>> runListT [ (x, str) | x <- listT_xs, str <- listT_g x ]
[(1,"1"),(1,"1"),(1,"1"),(2,"2"),(2,"2"),(2,"2"),(3,"3"),(3,"3"),(3,"3")]
To solve these problems you might want to experiment with pipes. You'll get the "correct" solution there, though it won't look nearly as much like a list comprehension.
I have a simple list that I would like to iterate over "yield"ing between each element and printing that element to the output. I am trying to use the ContT monad to do this but running into issues. Here's what I have so far:
data K a = Nil | K (a,() -> K a)
listIterator :: (Monad m) => [r] -> m (K r)
listIterator [] = return Nil
listIterator (x:xs) = return (ContT (\k -> K (x,k))) >> listIterator xs
runIterator :: IO ()
runIterator = do
a <- listIterator ([1,2,3] :: [Int])
let loop Nil = liftIO $ print "nil"
loop (K (curr,newI)) =
do
liftIO $ print curr
loop (newI ())
loop a
The expected output is:
1
2
3
nil
What I get is:
nil
Any help is appreciated!
listIterator (x:xs) = return (ContT (\k -> K (x,k))) >> listIterator xs
does not do what you expect, equational reasoning
listIterator (x:xs)
= return (ContT (\k -> K (x,k))) >> listIterator xs
= (return (ContT (\k -> K (x,k)))) >>= \_ -> listIterator xs
= (\_ -> listIterator xs) (ContT (\k -> K (x,k)))
= listIterator xs
I'm not sure exactly why you want to use an iterator. Haskell is already lazy, so iteration patterns like this are mostly used only when you have resource management issues that need to interact well with a demand driven usage pattern. And, you don't need the continuation monad at all:
Instead of writing the K constructor to take a tuple it is more idiomatic to
data K a = Nil | K a (() -> K a)
intuitively, the type for the listIterator does not use its monadic structure: it just constructs a value, so
listIterator ::[r] -> K r
listIterator [] = Nil
listIterator (x:xs) = K x (\_ -> listIterator xs)
now life is trivial
runIterator :: IO ()
runIterator = do
let a = listIterator ([1,2,3] :: [Int])
loop Nil = liftIO $ print "nil"
loop (K curr newI) =
do
liftIO $ print curr
loop (newI ())
loop a
which would probably be best to write without the use of do notation.
This may not be the answer you were looking for, but if you are interested in this style of programming, you should look into pipes and similar libraries. (conduit is the rising star in the "real world", but pipes provides a simpler tool for teaching which is why I use it here.)
$ cabal update && cabal install pipes
Pipes are like iterators, except they come in three flavors: those that can acquire input (Consumers), those that produce output (Producers), and those that do both (Pipes). If you connect pipes such that the input and output ends are all satisfied, then it is called a "Pipeline", and it is a self-contained unit that can be run without any additional input.
Pipe provides a monad instance for convenience in creating pipes. The >+> operator connects two pipes together.
import Control.Pipe
import Control.Monad.Trans.Class
import Control.Monad.IO.Class
-- annoyingly, Pipe does not provide a MonadIO instance
instance (MonadIO m) => MonadIO (Pipe a b m) where
liftIO = lift . liftIO
listIterator :: Monad m => [a] -> Producer (Maybe a) m ()
listIterator (x:xs) = yield (Just x) >> listIterator xs
listIterator [] = yield Nothing
printer :: (MonadIO m, Show a) => Consumer (Maybe a) m ()
printer = do
mx <- await
case mx of
Just x -> liftIO (print x) >> printer
Nothing -> liftIO (putStrLn "nil")
main = runPipe $ listIterator [1, 2, 3] >+> printer
The source for Control.Pipe is delightfully simple, especially if you have been reading Gabriel's recent blog posts about Free monads, particularly Why free monads matter and Purify code using free monads.
my goal is to write Haskell function which reads N lines from input and joins them in one string. Below is the first attempt:
readNLines :: Int -> IO String
readNLines n = do
let rows = replicate n getLine
let rowsAsString = foldl ++ [] rows
return rowsAsString
Here haskell complaints on foldl:
Couldn't match expected type [a]'
against inferred type(a1 -> b -> a1)
-> a1 -> [b] -> a1'
As I understand type of rows is [IO String], is it possible some how join such list in a single IO String?
You're looking for sequence :: (Monad m) => [m a] -> m [a].
(Plus liftM :: Monad m => (a1 -> r) -> m a1 -> m r and unlines :: [String] -> String, probably.)
Besides what ephemient points out, I think you have a syntax issue: The way you're using the ++ operator makes it look like you are trying to invoke the ++ operator with operands foldl and []. Put the ++ operator in parentheses to make your intent clear:
foldl (++) [] rows
The functions you are looking for is is sequence, however it should be noted that
sequence (replicate n f)
is the same as
replicateM n f
And foldl (++) [] is equivalent to concat. So your function is:
readNLines n = liftM concat (replicateM n getLine)
Alternatively if you want to preserve line breaks:
readNLines n = liftM unlines (replicateM n getLine)
The shortest answer I can come up with is:
import Control.Applicative
import Control.Monad
readNLines :: Int -> IO String
readNLines n = concat <$> replicateM n getLine
replicate returns a list of IO String actions. In order to perform these actions, they need to be run in the IO monad. So you don't want to join an array of IO actions, but rather run them all in sequence and return the result.
Here's what I would do
readNLines :: Int -> IO String
readNLines n = do
lines <- replicateM n getLine
return $ concat lines
Or, in applicative style:
import Control.Applicative
readNLines :: Int -> IO String
readNLines n = concat <$> replicateM n getLine
Both of these use the monadic replicate (replicateM), which evaluates a list of monadic values in sequence, rather than simply returning a list of actions