I've got the following function:
lines' :: [IO String]
lines' = getLine : lines'
I was hoping I could just use all the mighty list functions on
this list, like filter etc. But my knowledge about the IO monad in
haskell is improvable.
The list-of-io_stuff-concept convinced me after using Rx for C#.
Is there any way to do what I want in haskell ?
Something like:
ten_lines :: [IO String]
ten_lines = take 10 lines'
proc_lines :: [IO String]
proc_lines = [ (l, length l) | l <- lines' ]
Thanks!
There are a whole bunch of normal list functions modified to work with monads in Control.Monad. Of particular interest to your question:
sequence :: Monad m => [m a] -> m [a]
mapM :: Monad m => (a -> m b) -> [a] -> m [b]
filterM :: Monad m => (a -> m Bool) -> [a] -> m [a]
foldM :: Monad m => (a -> b -> m a) -> a -> [b] -> m a
(sequence and mapM are actually exported by the prelude and available by default.)
For example, let's take a look at the type of your take 10 lines' example:
Prelude Control.Monad> :t take 10 lines'
take 10 lines' :: [IO String]
We want to turn this [IO String] into a single IO [String] action. This is exactly what sequence does! We can tell this by the type signature. So:
sequence $ take 10 lines'
will do what you want.
Most of these functions also have a version ending in _, like sequence_. This has exactly the same effect as the normal function except it throws away the result, returning () instead. That is, sequence_ :: [m a] -> m (). This is a good choice whenever you don't actually care about the result for two reasons: it's more explicit about your intentions and the performance can be better.
So if you wanted to print 10 lines rather than get them, you would write something like this:
printLines = putStrLn "foo" : printLines
main = sequence_ $ take 10 printLines
Tikhon's solution is the simplest one, but it has one major deficiency: it will not produce any results until processing the entire list and it will overflow if you process too large of a list.
A solution closer to C#'s Rx would be to use a streaming library like pipes.
For example, you can define a Producer that generates Strings from user input:
import Control.Monad
import Control.Proxy
lines' :: (Proxy p) => () -> Producer p String IO r
lines' () = runIdentityP $ forever $ do
str <- lift getLine
respond str
Then you can define a stage that takes 10 lines:
take' :: (Monad m, Proxy p) => Int -> () -> Pipe p a a m ()
take' n () = runIdentityP $ replicateM_ n $ do
a <- request ()
respond a
... and then a processing stage:
proc :: (Monad m, Proxy p) => () -> Pipe p String (String, Int) m r
proc () = runIdentityP $ forever $ do
str <- request ()
respond (str, length str)
... and a final output stage:
print' :: (Proxy p, Show a) => () -> Consumer p a IO r
print' () = runIdentityP $ forever $ do
a <- request ()
lift $ print a
Now you can compose those into a processing chain and run it:
main = runProxy $ lines' >-> take' 10 >-> proc >-> print'
... and it will output the processed result instantly after entering each line, rather than providing the result as a batch at the end:
$ ./pipes
Apple<Enter>
("Apple",5)
Test<Enter>
("Test",4)
123<Enter>
("123",3)
4<Enter>
("4",1)
5<Enter>
("5",1)
6<Enter>
("6",1)
7<Enter>
("7",1)
8<Enter>
("8",1)
9<Enter>
("9",1)
10<Enter>
("10",2)
$
In practice, you don't have to define these pipes yourself. You can assemble the same chain from components in the pipes standard library:
>>> runProxy $ stdinS >-> takeB_ 10 >-> mapD (\x -> (x, length x)) >-> printD
<exact same behavior>
Related
How can I use pure functions inside IO functions? :-/
For example: I'm reading a file (IO function) and I want to parse its context, a string, by using a pure function with referential transparency.
It seems such worlds, pure functions and IO functions, are separated. How can I possibly bridge them?
The simplest way is to use fmap, which has the following type:
fmap :: (Functor f) => (a -> b) -> f a -> f b
IO implements Functor, which means that we can specialize the above type by substituting IO for f to get:
fmap :: (a -> b) -> IO a -> IO b
In other words, we take some function that converts as to bs, and use that to change the result of an IO action. For example:
getLine :: IO String
>>> getLine
Test<Enter>
Test
>>> fmap (map toUpper) getLine
Test<Enter>
TEST
What just happened there? Well, map toUpper has type:
map toUpper :: String -> String
It takes a String as an argument, and returns a String as a result. Specifically, it uppercases the entire string.
Now, let's look at the type of fmap (map toUpper):
fmap (map toUpper) :: IO String -> IO String
We've upgraded our function to work on IO values. It transforms the result of an IO action to return an upper-cased string.
We can also implement this using do notation, to:
getUpperCase :: IO String
getUpperCase = do
str <- getLine
return (map toUpper str)
>>> getUpperCase
Test<Enter>
TEST
It turns out that every monad has the following property:
fmap f m = do
x <- m
return (f x)
In other words, if any type implements Monad, then it should always be able to implement Functor, too, using the above definition. In fact, we can always use the liftM as the default implementation of fmap:
liftM :: (Monad m) => (a -> b) -> m a -> m b
liftM f m = do
x <- m
return (f x)
liftM is identical to fmap, except specialized to monads, which are not as general as functors.
So if you want to transform the result of an IO action, you can either use:
fmap,
liftM, or
do notation
It's really up to you which one you prefer. I personally recommend fmap.
You can also consider liftM function from Control.Monad.
A little example to help you (run it into ghci as you are under the IO Monad)
$ import Control.Monad -- to emerge liftM
$ import Data.Char -- to emerge toUpper
$ :t map to Upper -- A pure function
map toUpper :: [Char] -> [Char]
$ :t liftM
liftM :: Monad m => (a1 -> r) -> m a1 -> m r
$ liftM (map toUpper) getLine
The actual answer is as follows:
main = do
val <- return (purefunc ...arguments...)
...more..actions...
return wraps it in the appropriate monad so that do can assign it to val.
Alex Horsman helped me. He said:
"Perhaps I'm misunderstanding, but that sounds pretty simple?
do {x <- ioFunc; return (pureFunc x)}"
And then I solved my problem:
import System.IO
import Data.List
getFirstPart line Nothing = line
getFirstPart line (Just index) = fst $ splitAt index line
eliminateComment line =
getFirstPart line $ elemIndex ';' line
eliminateCarriageReturn line =
getFirstPart line $ elemIndex '\r' line
eliminateEntersAndComments :: String -> String
eliminateEntersAndComments text =
concat $ map mapFunction $ lines text
where
mapFunction = (++ " ") . eliminateCarriageReturn . eliminateComment
main = do {
contents <- readFile "../DWR-operators.txt";
return (eliminateEntersAndComments contents)
}
I'm playing around with the leveldb bindings.
I'm wondering if it's possible to take a function like
MonadResource m => a -> m b
And convert it to
MonadResource m => m (a -> IO b))
It can definitely be done, but it's dangerous. Let's demonstrate first the how, by extracting the internal state of the ResourceT:
import Control.Monad.IO.Class
import Control.Monad.Trans.Resource
import Control.Monad.Trans.Resource.Internal
data Foo = Foo Int
deriving Show
getFoo :: MonadResource m => Int -> m Foo
getFoo i = fmap snd $ allocate
(do
putStrLn $ "allocating Foo with " ++ show i
return $ Foo i)
(\(Foo x) -> putStrLn $ "Freeing Foo " ++ show x)
stripLayer :: MonadResource m => (a -> ResourceT IO b) -> m (a -> IO b)
stripLayer f = do
is <- liftResourceT getInternalState
return $ \a -> runInternalState (f a) is
main :: IO ()
main = do
getFoo' <- runResourceT $ stripLayer $ getFoo
getFoo' 42 >>= print
Unfortunately the output from this isn't what we'd hope for:
allocating Foo with 42
Foo 42
Notice how the "Freeing" line is never called. This is because, by the time we use getFoo', the runResourceT call has already exited, which is how we guarantee that all resources are freed. You can safely get away with this trick if you're disciplined and make sure everything lives inside the runResourceT call, but the type system won't help you. To see what this will look like:
main :: IO ()
main = runResourceT $ do
getFoo' <- stripLayer $ getFoo
liftIO $ getFoo' 42 >>= print
How can a output a list of strings using putStr and map? I want to do something like:
s=["test1","test2"]
map putStr s
But have no experience with monads and don't know how to get it right...
Any kind of hint is enormously welcome!
The correct thing to do here is use mapM_ :: Monad m => (a -> m b) -> [a] -> m (). But if you'd like to learn a little about some useful Prelude functions...
We have two functions here,
map :: (a -> b) -> [a] -> [b]
putStr :: String -> IO ()
if we substitute the type of putStr into map (ie. a ~ String, b ~ IO ()) we get
map putStr :: [String] -> [IO ()]
so this takes a list of strings and gives us a list of IO () actions; IO computations that don't return anything usefull.
We'd like to turn that [IO ()] into something like IO (...) because we need IO to be the outermost layer in order to use it in main :: IO ()
The function sequence :: Monad m => [m a] -> m [a] from the Prelude is exactly what we need. It takes a list of monadic actions, executes them and returns the results in a list wrapped in the monad. Intuitively it moves the monad to the outermost layer.
sequence . map putStr :: [String] -> IO [()]
This is quite close, but we still have IO [()] instead of IO (), we don't really care about the [()] result and it'd be nice to ignore it. Again, the Prelude has what we need: sequence_ :: Monad m => [m a] -> m () which executes each monadic action in the list and ignores their return values.
Note that mapM_ is defined as
mapM_ f = sequence_ . map f
The type of map is:
map :: (a -> b) -> [a] -> [b]
this means that, since putStr returns an IO (), your expression will return a [IO ()].
You can, instead, use mapM_ (imported from Prelude) that will ignore the return type from the mapping and return an IO () which is a suitable return type for main:
main = do
let s=["test1","test2"]
mapM_ putStr s
Live demo
I'm new to Haskell and FP so this question may seem silly.
I have a line of code in my main function
let y = map readFile directoryContents
where directoryContents is of type [FilePath]. This in turn (I think) makes y type [IO String] , so a list of strings - each string containing the contents of each file in directoryContents.
I have a functions written in another module that work on [String] and String but I'm unclear as how to call/use them now because y is of type [IO String]. Any pointers?
EDIT:
It was suggested to me that I want to use mapM instead of map, so:
let y = mapM readFile directoryContents , and y is now type IO [String], what do I do from here?
You're correct, the type is y :: [IO String].
Well, there are essentially main two parts here:
How to turn [IO String] into IO [String]
[IO String] is a list of of IO actions and what we need is an IO action that carries a list of strings (that is, IO [String]). Luckily, the function sequence provides exactly what we need:
sequence :: Monad m => [m a] -> m [a]
y' = sequence y :: IO [String]
Now the mapM function can simplify this, and we can rewrite y' as:
y' = mapM readFile directoryContents
mapM does the sequence for us.
How to get at the [String]
Our type is now IO [String], so the question is now "How do we get the [String] out of the IO?" This is what the function >>= (bind) does:
(>>=) :: Monad m => m a -> (a -> m b) -> m b
-- Specialized to IO, that type is:
(>>=) :: IO a -> (a -> IO b) -> IO b
We also have a function return :: Monad m => a -> m a which can put a value "into" IO.
So with these two functions, if we have some function f :: [String] -> SomeType, we can write:
ourResult = y' >>= (\theStringList -> return (f theStringList)) :: IO SomeType
Functions can be "chained" together with the >>= function. This can be a bit unreadable at times, so Haskell provides do notation to make things visually simpler:
ourResult = do
theStringList <- y'
return $ f theStringList
The compiler internally turns this into y' >>= (\theStringList -> f theStringList), which is the same as the y' >>= f that we had before.
Putting it all together
We probably don't actually want y' floating around, so we can eliminate that and arrive at:
ourResult = do
theStringList <- mapM readFile directoryContents
return $ f theStringList
Even more simplification
It turns out, this doesn't actually need the full power of >>=. In fact, all we need is fmap! This is because the function f only has one argument "inside" of IO and we aren't using any other previous IO result: we're making a result then immediately using it.
Using the law
fmap f xs == xs >>= return . f
we can rewrite the >>= code to use fmap like this:
ourResult = fmap f (mapM readFile directoryContents)
If we want to be even more terse, there is an infix synonym for fmap called <$>:
ourResult = f <$> mapM readFile directoryContents
So lately I have a list of strings, and need to independently go over each one and perform some IO function.
So basically what I have is this:
goOverList :: [String] -> IO ()
goOverList (x:[]) = do
putStrLn x
goOverList (x:xs) = do
goOverList [x]
goOverList xs
main = do
let myList = ["first", "second", "third"]
goOverList myList
My IO is a bit more complicated but that is the gist of it (needing to have a function go over a list and do IO based on the list member) I was hoping someone might show me how to do this better.
Your goOverList function is almost equivalent to mapM_ putStrLn. (Just almost because mapM_ also works with the empty list while your function does not).
mapM is a function that applies a function of type a -> IO b¹ to each item in a list of as and gives you back an IO² with a list of bs. mapM_ is the same as mapM except that it doesn't store the results in a list (which doesn't make sense for actions that return () like putStrLn does).
¹ Actually it's more general than that: The function has type a -> m b where Monad m, but in this case m is IO.
² Again it's actually m.
sepp2k and solrize are right to recommend mapM_. But, in the spirit of teaching you to fish instead of giving you a fish, here's something you can try in the future:
Try to come up with the type signature of the operation that you need. For example, in your case, you want something of type (String -> IO ()) -> [String] -> IO ().
Go to the Hoogle search engine for Haskell libraries and search for that type.
That one has no results, so try modifying the type a bit to make it more generic. Replace String with a to get (a -> IO ()) -> [a] -> IO (), and search for that.
Now the third result of the second search is mapM_ :: Monad m => (a -> m b) -> [a] -> m (), which is exactly what you want. (The first answer, closeFdWith :: (Fd -> IO ()) -> Fd -> IO () is not a relevant result; the second, traverse_ :: (Foldable t, Applicative f) => (a -> f b) -> t a -> f () is relevant but a bit more complicated to understand and use.)
First, easy improvement:
goOverList' :: [String] -> IO ()
goOverList' [] = return ()
goOverList' (x:xs) = do
putStrLn x
goOverList' xs
The base case for recursion should be the empty list: in that case, you simply return the IO action return () which does nothing. When you have one or more elements, you print it and continue with the rest of the list, simple as that.
The same exact thing is achievable in a way more compact definition with mapM_ :: Monad m => (a -> m b) -> [a] -> m (): it is the same as the regular map, except that it works with monadic actions. Instead of returning the collection of results m [b] like the regular mapM would do, it throws it away. It works just fine for you in this case, as you're are only interested in printing out the elements of he list.
goOverList'' :: [String] -> IO ()
goOverList'' = mapM_ putStrLn
In order to be even more general, we could rely on print :: Show a => a -> IO () instead of putStrLn and accept in input every list of "showable" items:
goOverList''' :: (Show a) => [a] -> IO ()
goOverList''' = mapM_ print
data T = One | Two | Three deriving (Show)
main = do
let myList = [One, Two, Three]
goOverList''' myList
Your goOverList function can be written mapM_ putStrLn where mapM_ is a function in the standard Prelude.
You can also simplify your own implementation:
goOverList :: [String] -> IO ()
goOverList [] = return ()
goOverList (x:xs) = do
putStrLn x
goOverList xs