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
Related
I'm working on the HackerRank problem sets. The following Haskell correctly solves the problem, but I have a hunch that it's not what a seasoned veteran would write. I'd appreciate any input on how to make this prettier/more expressive.
compTrips :: [Int] -> [Int] -> [Int]
compTrips as bs =
let oneIfGreater a b = if a > b
then 1
else 0
countGreater x y = foldr (+) 0 $ zipWith oneIfGreater x y
in [countGreater as bs, countGreater bs as]
main = do
line1 <- getLine
line2 <- getLine
let alice = map read $ words line1
let bob = map read $ words line2
let (a:b:_) = compTrips alice bob
putStrLn $ show a ++ " " ++ show b
I don't like compTrips's type; it's too permissive. Declaring that it can return an [Int] says you don't know how many Ints it will return. But you know it will be exactly two; so:
compTrips :: [Int] -> [Int] -> (Int, Int)
In the implementation, I'd prefer sum to foldr (+) 0; it says more clearly what you intend, and also, as a side benefit, sum uses a strict left fold and so sometimes can be more memory-efficient:
compTrips as bs =
let oneIfGreater a b = if a > b
then 1
else 0
countGreater x y = sum $ zipWith oneIfGreater x y
in (countGreater as bs, countGreater bs as)
I don't like that we compute each comparison twice. I'd want to split out the computation of the comparison from the counting up of which way the comparison went. At the same time, I would switch over from using sum and your custom fromEnum implementation (namely, oneIfGreater) to using a combination of length and filter (or, in this case where we want both "sides" of the filter, partition). So:
import Data.Bifunctor
import Data.List
compTrips as bs = bimap length length . partition id $ zipWith (>) as bs
I think you can abstract the reading and parsing of a line so that this logic is not replicated. So:
readInts :: IO [Int]
readInts = do
line <- getLine
pure (map read $ words line)
main = do
alice <- readInts
bob <- readInts
let (a, b) = compTrips alice bob
putStrLn $ show a ++ " " ++ show b
I don't like read's type, for almost exactly the same reason I don't like compTrips's type. In this case, declaring that it can accept any String says it can parse anything, when in reality it can only parse a very specific language. readMaybe has a better type, saying that it may sometimes fail to parse:
readMaybe :: Read a => String -> Maybe a
There's a large collection of Applicative-based methods for combining the error-handling of many calls to readMaybe; especially check out traverse (which is a bit like map, but with the capability to handle errors) and liftA2 (which can convert any binary operation into one that can handle errors).
One way we could use it would be to print a nice error message when it failed, so:
import System.IO
import Text.Read
readInts = do
line <- getLine
case traverse readMaybe (words line) of
Just person -> pure person
Nothing -> do
hPutStrLn stderr "That doesn't look like a space-separated collection of numbers! Try again."
readInts
(Other error-handling options exist.)
That leaves us with the following final program:
import Data.Bifunctor
import Data.List
import System.IO
import Text.Read
compTrips :: [Int] -> [Int] -> (Int, Int)
compTrips as bs = bimap length length . partition id $ zipWith (>) as bs
readInts :: IO [Int]
readInts = do
line <- getLine
case traverse readMaybe (words line) of
Just person -> pure person
Nothing -> do
hPutStrLn stderr "That doesn't look like a space-separated collection of numbers! Try again."
readInts
main :: IO ()
main = do
alice <- readInts
bob <- readInts
let (a, b) = compTrips alice bob
putStrLn $ show a ++ " " ++ show b
Although the text is actually a bit longer, I would consider this a more idiomatic implementation; the main two things being to pay careful attention to avoiding the use of partial functions (like read and your partial pattern match on the result of compTrips) and increasing the reliance on library-provided bulk operations when handling lists (like our use of length and partition).
You can obain the number of elements that match with length . filter. So you can here count the number of matches with:
compTrips :: [Int] -> [Int] -> (Int, Int)
compTrips as bs = (f as bs, f bs as)
where f xs = length . filter id . zipWith (>) xs
It is usually better to return tuples to return "multiple" values. Since then these two values can have a different type, and furthermore the type checking mechansim will guarantee that you return two items.
You can perform fmap :: Functor f => (a -> b) -> f a -> f b or its operator synonym (<$>) :: Functor f => (a -> b) -> f a -> f b on the results of getLine to "post-process" the result:
main :: IO ()
main = do
line1 <- map read . words <$> getLine
line2 <- map read . words <$> getLine
let (a, b) = compTrips line1 line2
putStrLn (show a ++ " " ++ show b)
You may perhaps do like
λ> :{
λ| getLine >>= return . map (read :: String -> Int) . words
λ| >>= \l1 -> getLine
λ| >>= return . map (read :: String -> Int) . words
λ| >>= \l2 -> return $ zipWith (\a b -> if a > b then 1 else 0) l1 l2
λ| :}
1 2 3 4 5
2 3 1 4 2
[0,0,1,0,1]
I'm trying to write a function with StateT only to learn more about it.
In f, I'd like to access to the Int in the last type argument of StateT [Int] IO Int:
f :: StateT [Int] IO Int
f = state $ \xs -> update (error "I want a") xs
update :: Int -> [Int] -> (Int, [Int])
update x [] = (x, [])
update x (y:ys) = (x+y, ys)
Here's how I'd like to call it:
let x = return 55 :: StateT [Int] IO Int
Referencing runStateT:
*Main> :t runStateT
runStateT :: StateT s m a -> s -> m (a, s)
I'd expect to run it:
runStateT (f x) [1,2,3]
to get the following from GHCI, i.e. the IO (Int, [Int]) gets printed:
(56, [2,3])
since the inner a, i.e. 55, + 1, i.e. from [1,2,3], returns (56, [2,3]).
How can I write the above function, getting access to the a?
Ok, here's what say you want:
>>> let x = return 55 :: StateT [Int] IO Int
>>> runStateT (f x) [1,2,3]
(56, [2,3])
So let's work backwards from that.
From the use of f, we can infer its type -
f :: StateT [Int] IO Int -> StateT [Int] IO Int
Note the difference from your given type for f in the question - namely f is a function between values of type StateT [Int] IO Int, not a value of that type.
To define f, we need (>>=) :: Monad m => m a -> (a -> m b) -> m b. This will allow us to take our input of type StateT [Int] IO Int and run some computation on the Int the input computes.
f x = x >>= \i -> state (splitAt 1) >>= \[j] -> return (i + j)
or, using do-notation:
f x = do
i <- x
[j] <- state (splitAt 1)
return (i + j)
Which gives us exactly the result we want.
While this works, it's highly non-idiomatic. Rather than passing monadic values in as inputs to functions and binding them inside the function, it's far more common to define functions that take regular values and return monadic ones, using the bind operator (>>=) outside.
So it'd be far more normal to define
shiftAdd :: Int -> StateT [Int] IO Int
shiftAdd i = do
[j] <- state (splitAt 1)
return (i + j)
So now we can run not only
>>> runStateT (shiftAdd 55) [1,2,3]
(56,[2,3])
but also
>>> runStateT (shiftAdd 55 >>= shiftAdd >>= shiftAdd)
(61,[])
It's still not as idiomatic as it could be as:
I made it unnecessarily partial by using splitAt (it'll throw an exception if the state list is empty)
it's unnecessarily specific (doesn't use IO at all, but we can't use it with other base monads)
Fixing that up gives us:
shiftAdd' :: (Monad m, Num a) => a -> StateT [a] m a
shiftAdd' i = state $ \js -> case js of
[] -> (i, [])
j : js -> (i + j, js)
Which works just fine:
>>> runStateT (return 55 >>= shiftAdd') [1,2,3]
(56,[2,3])
>>> runStateT (return 55 >>= shiftAdd' >>= shiftAdd' >>= shiftAdd') [1,2,3]
(61,[])
>>> runStateT (return 55 >>= shiftAdd' >>= shiftAdd' >>= shiftAdd') []
(55,[])
As you can see, I wrote program, e.g:
test "12 124 212" = Right [12, 124, 212]
test "43 243 fs3d 2" = Left "fs3d is not a number"
test :: String -> Either String [Int]
test w = iter [] $ words w
where
iter acc [] = Right (reverse acc)
iter acc (x:xs) = if (all isDigit x) then
iter ((read x):acc) xs
else
Left (x++ "is not a number")
A am starting learning monads. Could you show me how to implement it using monads ?
I think you are looking for traverse/mapM (they're the same for lists). Also you can use readEither for simplification:
import Data.Traversable (traverse)
import Data.Bifunctor (first)
import Text.Read (readEither)
test :: String -> Either String [Int]
test = traverse parseItem . words
parseItem :: String -> Either String Int
parseItem x = first (const $ x++" is not a number") $ readEither x
So what does mapM do? It basically implements the recursion over the list that you did manually. However, unlike the standard map function it takes a monadic function (parseItem in our case, where Either String is a monad) and applies one step on the list after the other:
iter [] = Right []
iter (x:xs) = do
r <- parseItem x
rs <- iter xs
return (r:rs)
Bergi's answer is just right, but maybe you'll find it easy to understand presented this way:
test :: String -> Either String [Int]
test str = traverse parseNumber (words str)
parseNumber :: String -> Either String Int
parseNumber str
| all isDigit str = Right (read str)
| otherwise = Left (str ++ " is not a number")
The other thing I'd recommend is don't write tail-recursive accumulator loops like iter in your example. Instead, look at library documentation and try to find list functions that do what you want. In this case, as Bergi correctly pointed out, traverse is exactly what you want. It will take some study to get fully comfortable with this function, though. But given how the Monad instance of Either and the Traversable instance of lists work, the traverse in this example works like this:
-- This is the same as `traverse` for lists and `Either`
traverseListWithEither :: (a -> Either err b) -> [a] -> Either err [b]
traverseListWithEither f [] = Right []
traverseListWithEither f (a:as) =
case f a of
Left err -> Left err
Right b -> mapEither (b:) (traverseListWithEither f as)
-- This is the same as the `fmap` function for `Either`
mapEither :: (a -> b) -> Either e a -> Either e b
mapEither f (Left e) = Left e
mapEither f (Right a) = Right (f a)
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'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 :)