Doing recursion within an IO monad - haskell

I have been trying to figure out how to do recursion within an IO monad.
I am familiar with doing recursion with pure functions, but have not been able to transfer this knowledge to IO monads.
Recursion with pure functions
I'm comfortable with doing recursion with pure functions such as the foo function below.
foo (x:y:ys) = foo' x y ++ foo ys
A function with IO [String] output
I made a function like goo below that does what I need and has an IO output.
goo :: String -> String -> IO [String]
goo xs ys = goo' xs ys
Trying to get recursion inside an IO monad
When I try to do recursion within an IO monad (e.g., a "main" function) I cannot. I've looked up liftM, replicateM, and the undo-the-IO <- operator or function. I want an IO monad like hoo or hoo' (apologies for the gibberish that follows).
hoo :: [String] -> IO [String]
hoo (xs:ys:yss) = do
let rs = goo xs ys ++ hoo yss
return rs
or
hoo' :: [String] -> IO [String]
hoo' (xs:ys:yss) = do
rs <- goo xs ys
let gs = rs ++ hoo' yss
return gs
(BTW, in case you are wondering what my project is, I'm writing a Genetic Algorithm program from scratch for a course. My goo function takes two parents and breeds two offspring, which are returned as an IO because goo uses a random number generator. What I need to do is to to use a recursive hoo function to use goo to breed 20 offspring from a list of 20 parents. The idea I have is to take the first two parents in the list, breed two offspring, take the next two parents on the list, breed another pair of offspring, so on and so forth.)

If you find do notation confusing, my recommendation would be to not use it at all. You can do everything you need with >>=. Just pretend its type is
(>>=) :: IO a -> (a -> IO b) -> IO b
That said, let's look at your code.
let in a do block gives a name to some value. That's the same thing it does outside of do, so that's not helpful here (it gives you no additional power).
<- is more interesting: It acts as an "extract a value from IO locally" construct (if you squint a bit).
hoo :: [String] -> IO [String]
hoo (xs:ys:yss) = do
-- The right-hand side (goo xs ys) has type IO [String], ...
rs <- goo xs ys
-- ... so rs :: [String].
-- We can apply the same construct to our recursive call:
hs <- hoo yss
-- hoo yss :: IO [String], so hs :: [String].
let gs = rs ++ hs
return gs
As mentioned above, let just binds a name to a value, so we don't really need it here:
hoo :: [String] -> IO [String]
hoo (xs:ys:yss) = do
rs <- goo xs ys
hs <- hoo yss
return (rs ++ hs)
Alternatively, without do notation and <- we'd do it as follows.
(>>=) :: IO a -> (a -> IO b) -> IO b
>>= takes an IO value and a callback function, and it runs the function on the "unwrapped" value (a). That means within the function we get local access to the value as long as the result of the whole thing is IO b again (for some arbitrary type b).
hoo :: [String] -> IO [String]
hoo (xs : ys : yss) =
goo xs ys -- :: IO [String]
...
We have an IO [String] and we need to do something with [String], so we use >>=:
hoo :: [String] -> IO [String]
hoo (xs : ys : yss) =
goo xs ys >>= (\rs -> ...)
If you look at >>='s type signature, the role of a is played by [String] here
(rs :: [String]) and b is also [String] (because hoo as a whole needs to return IO [String]).
So what do we do in the ... part? We need to make a recursive call to hoo, which again results in an IO [String] value, so we use >>= again:
hoo :: [String] -> IO [String]
hoo (xs : ys : yss) =
goo xs ys >>= (\rs -> hoo yss >>= (\hs -> ...))
Again, hs :: [String] and ... better have type IO [String] to make the whole thing typecheck.
Now that we have rs :: [String] and hs :: [String], we can simply concatenate them:
hoo :: [String] -> IO [String]
hoo (xs : ys : yss) =
goo xs ys >>= (\rs -> hoo yss >>= (\hs -> rs ++ hs)) -- !
This is a type error. rs ++ hs :: [String], but the context requires IO [String]. Fortunately there's a function that can help us out:
return :: a -> IO a
Now it typechecks:
hoo :: [String] -> IO [String]
hoo (xs : ys : yss) =
goo xs ys >>= (\rs -> hoo yss >>= (\hs -> return (rs ++ hs)))
Due to the way Haskell syntax works (function bodies extend as far to the right as possible), most parens here are actually optional:
hoo :: [String] -> IO [String]
hoo (xs : ys : yss) =
goo xs ys >>= \rs -> hoo yss >>= \hs -> return (rs ++ hs)
And with a bit of reformatting the whole thing can be made to look pretty suggestive:
hoo :: [String] -> IO [String]
hoo (xs : ys : yss) =
goo xs ys >>= \rs ->
hoo yss >>= \hs ->
return (rs ++ hs)

do notation is very handy. Use it, it's your friend. We just need to follow its rules, were each thing going into its place must have a correct type, correspondingly.
You were very close:
goo :: String -> String -> IO [String]
{- hoo' :: [String] -> IO [String]
hoo' (xs:ys:yss) = do
rs <- goo xs ys
let gs = rs ++ hoo' yss
return gs -}
hoo'' :: [String] -> IO [String]
hoo'' (xs:ys:yss) = do
rs <- goo xs ys -- goo xs ys :: IO [String] -- rs :: [String]
qs <- hoo'' yss -- hoo'' yss :: IO [String] -- qs :: [String]
let gs = rs ++ qs -- gs :: [String]
return gs -- return gs :: IO [String]
In do notation, with x <- foo, when foo :: IO a, we have x :: a. That's it. (Some more explanations are e.g. here).
As for recursion, it is achieved with do notation just as it is achieved in pure code: by naming things, and referring to the same name from inside the expression defining that name, whether it is a pure expression or a do notation.
Recursion is a leap of faith. We don't care how the thing is defined -- we assume it is defined correctly so we can just refer to it by its name. As long as the types fit.

To do this with do notation, you need to bind the results of every IO action in order to use those results in pure expressions such as let rs =…++…, like so:
hoo :: [String] -> IO [String]
hoo (xs:ys:yss) = do
g <- goo xs ys
h <- hoo yss
let rs = g ++ h
return rs
However, often you don’t want to introduce a temporary name for the result of every action, so in typical Haskell code, there are a few combinators that make this kind of thing more compact. Here you can use liftA2:
liftA2
:: Applicative f
-- Given a pure function to combine an ‘a’ and a ‘b’ into a ‘c’…
=> (a -> b -> c)
-- An action that produces an ‘a’…
-> f a
-- And an action that produces a ‘b’…
-> f b
-- Make an action that produces a ‘c’.
-> f c
Like this:
hoo (xs:ys:yss) = liftA2 (++) (goo xs ys) (hoo yss)
liftA2 only works for functions of two arguments, though; for applying functions of other numbers of arguments, you can use the Functor operator <$> (an alias of fmap) and the Applicative operator <*>:
(<$>)
:: Functor f
-- Given a pure function to transform an ‘a’ into a ‘b’…
=> (a -> b)
-- And an action that produces an ‘a’…
-> f a
-- Make an action that produces a ‘b’.
-> f b
(<*>)
:: Applicative f
-- Given an action that produces a function from ‘a’ to ‘b’…
=> f (a -> b)
-- And an action that produces an ‘a’…
-> f a
-- Make an action that produces a ‘b’.
-> f b
These can be combined like so:
(++) <$> goo xs ys :: IO ([String] -> [String])
-- f (a -> b)
hoo yss :: IO [String]
-- f a
hoo (xs:ys:yss) = (++) <$> goo xs ys <*> hoo yss :: IO [String]
-- f b
That is, fmapping (++) over the result of goo xs ys using <$> is an action that returns a partially applied function, and <*> produces an action that applies this function to the result of hoo yss.
(There is a law which states that f <$> x is equivalent to pure f <*> x—that is, if you have an action pure f that just returns a function f, unwrap that action and apply it to the result of x using <*>, then that’s the same as just applying the pure function to the action with <$>.)
Another example of using this with a function of 3 arguments:
cat3 a b c = a ++ b ++ c
main = do
-- Concatenate 3 lines of input
result <- cat3 <$> getLine <*> getLine <*> getLine
putStrLn result
You can think of all of these combinators as different kinds of application operators, like ($):
($) :: (a -> b) -> a -> b
(<$>) :: (a -> b) -> f a -> f b
(<*>) :: f (a -> b) -> f a -> f b
(=<<) :: (a -> f b) -> f a -> f b
($) applies a pure function to a pure argument
(<$>) applies a pure function to the result of an action
(<*>) applies a pure function resulting from an action to the result of another action
(=<<) (the flipped version of (>>=)) applies a function returning an action to the result of an action

Related

A Haskell function that receives a List with different types and returns only an Integer List

I have a function like this:
[(String, [Int], Int)]
I desire a function that just returns a list of [Int].
Input example:
[("R1",[6,10,14],6),("R2",[8,10,14],8),("R3",[11,15,24],11)]
Output example (the behavior that I want of the output):
[6,8,10,11,14,15,24]
I've been thinking to create a function of input, like this:
function :: [(String, [Int], Int)]
function = [("R1",[6,10,14],6),("R2",[8,10,14],8),("R3",[11,15,24],11)]
And another to convert to what I desire, like this :
convert :: [(String, [Int], Int)] -> [Int]
convert [] = []
...
How can I develop the function convert?
First thing I like to do is lay out all the type signatures I think I'll need:
-- Something to use with fmap to get rid of the Strings
f :: (String, [Int], Int) -> ([Int], Int)
-- Something to cons the list with the Int
g :: ([Int], Int) -> [Int]
-- Our final goal:
convert :: [(String, [Int], Int)] -> [Int]
Now I like to think about how I can compose these together to get my final result:
fmap g . fmap f :: [(String, [Int], Int)] -> [[Int]]
And thanks to the functor laws you can actually rewrite that as:
fmap (g . f) :: [(String, [Int], Int)] -> [[Int]]
Thats pretty close, but we have two nested lists instead of one. Luckily list is a monoid which means that we can use mconcat :: [a] -> a to fold it. Thats a little confusing because mconcat operates on a list of monoidal a values. The more concrete signature for mconcat in our case would be:
mconcat :: [[Int]] -> [Int]
Where the monoid we are mappending is the inner list.
Regardless, what that allows us to do is write this:
mconcat . fmap (g . f) :: [(String, [Int], Int)] -> [Int]
Which is exactly the function we are trying to implement:
convert :: [(String, [Int], Int)] -> [Int]
convert = mconcat . fmap g . fmap f
where f = undefined
g = undefined
Now we just need to implement f and g:
f :: (String, [Int], Int) -> ([Int], Int)
f (_, xs, x) = (xs, x)
g :: ([Int], Int) -> [Int]
g (xs, x) = x:xs
g' :: ([Int], Int) -> [Int]
g' (xs, x) = xs ++ [x]
Depending what position you want x to go in you can use g or g'.
Then your final implementation would be something like (sort added to the composition to match your example result):
convert :: [(String, [Int], Int)] -> [Int]
convert = sort . mconcat . fmap g . fmap f
where f (_, xs, x) = (xs, x)
g (xs, x) = x:xs
Looking back at your question, it looks like the 3rd element of the triple is always a member of the second element? If thats the case, this function becomes even simpler:
convert :: [(String, [Int], Int)] -> [Int]
convert = sort . mconcat . fmap f
where f (_, xs, ) = xs
If you are worried about performance due to the final sort step, you could combine it with the concatenation by using foldr to rather then mconcat and do the sorting in the a -> b -> b.

Getting Access to 'a' in StateT

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,[])

Redefining monad list instance

I am attempting to redefine the monad list instance using newtype to create a wrapped list type, so as to allow this to be done at all, since it seems the Prelude definitions are unable to be overridden.
So far I have the following:
newtype MyList a = MyList { unMyList :: [a] }
deriving Show
myReturn :: a -> [a]
myReturn x = [x]
myBind :: [a] -> (a -> [b]) -> [b]
myBind m f = concat $ map f m
instance Monad MyList where
return x = MyList [x]
xs >>= f = undefined
As a beginner in Haskell, I am at a loss to know how to define the >>= operator for the instance, using my function for the definition of bind.
Should the myReturn and myBind functions have types using MyList rather than plain type variables? How does one do the packing and unpacking necessary to define >>= properly?
I am getting stuck on the function argument to map f, where f :: a -> [b], but it seems I need f :: a -> MyList b, but then map won't accept that as an argument.
Apologies for the confusion. All assistance appreciated.
[I am aware there is a similar question here: Redefine list monad instance but I'm afraid I cannot follow the answers there.]
You simply need to unwrap your MyList type, operate on it, then wrap it back up:
instance Monad MyList where
return x = MyList [x]
(MyList xs) >>= f = MyList . concat . map unMyList . map f $ xs
You can (and should) condense this to MyList $ concatMap (unMyList . f) xs, but I've left it expanded for illustrative purposes. You could simplify this definition by defining your own map and concat functions for MyList:
myMap :: (a -> b) -> MyList a -> MyList b
myMap f (MyList xs) = MyList $ map f xs
myConcat :: MyList (MyList a) -> MyList a
myConcat (MyList xs) = MyList $ concat $ map unMyList xs
myConcatMap :: (a -> MyList b) -> MyList a -> MyList b
myConcatMap f xs = myConcat $ myMap f xs
instance Monad MyList where
return x = MyList [x]
xs >>= f = myConcatMap f xs
And now it looks like the normal list instance:
instance Monad [] where
return x = [x]
xs >>= f = concatMap f xs

Get value from "IO a" is interpreted as list

I'm learning haskell with wikibooks.
Given is the signature. The solution to the problem is:
sequenceIO :: [IO a] -> IO [a]
sequenceIO [] = return []
sequenceIO (a:as) = do {v <-a ; vs <- (sequenceIO as) ; return (v : vs)}
My solution was (which does not work):
sequenceIO xs = return (foldl get [] xs)
where get ys act = do y <- act
ys ++ [y]
The "get" singled out as a function:
gett :: [a] -> IO a -> [a]
gett ys act = do y <- act
ys ++ y
will not work: a list as a second parameter is infered. Why? In the solution the v <-a works too.
The reason your solution doesn't work is that you cannot simply escape the IO Monad. Once you are in the IO Monad, you will always be. This is actually one of the really great things about Haskell, because you can't hide side effects and can tell by a functions type signature what type of effects it is allowed to do.
The type signature of your gett function should actually be
gett :: [a] -> IO a -> IO [a]
However you're function will still not typecheck:
1) A small oversight: ys ++ y should actually be ys ++ [y] (as it was for get in the where clause) because append (++) works on lists.
2) ys ++ [y] would still have the wrong type. It must be of type IO [a] but is of type [a]. You can get it into IO [a] by doing return $ ys ++ [y]. Here return has type return :: a -> IO a, it lifts any value into the monad.
gett is then:
gett :: [a] -> IO a -> IO [a]
gett ys act = do
y <- act
return $ ys ++ [y]
We're now getting close, but we're not quite there yet. Now the problem is with foldl get [] xs: foldl works on plain lists, not on lists inside monads. However, we can use foldM from here and write sequenceIO as follows:
sequenceIO :: [IO a] -> IO [a]
sequenceIO xs = foldM gett [] xs
which should typecheck and work.
Full program:
import Control.Monad (foldM) -- this only imports foldM from Control.Monad
gett :: [a] -> IO a -> IO [a]
gett ys act = do
y <- act
return $ ys ++ [y]
sequenceIO :: [IO a] -> IO [a]
sequenceIO xs = foldM gett [] xs
Now a good exercise is to figure out how foldM works ;)

Filter an infinite list of monadic values

Perhaps this is obvious, but I can't seem to figure out how to best filter an infinite list of IO values. Here is a simplified example:
infinitelist :: [IO Int]
predicate :: (a -> Bool)
-- how to implement this?
mysteryFilter :: (a -> Bool) -> [IO a] -> IO [a]
-- or perhaps even this?
mysteryFilter' :: (a -> Bool) -> [IO a] -> [IO a]
Perhaps I have to use sequence in some way, but I want the evaluation to be lazy. Any suggestions? The essence is that for each IO Int in the output we might have to check several IO Int values in the input.
Thank you!
Not doable without using unsafeInterleaveIO or something like it. You can't write a filter with the second type signature, since if you could you could say
unsafePerformIOBool :: IO Bool -> Bool
unsafePerformIOBool m = case mysteryFilter' id [m] of
[] -> False
(_:_) -> True
Similarly, the first type signature isn't going to work--any recursive call will give you back something of type IO [a], but then to build a list out of this you will need to perform this action before returning a result (since : is not in IO you need to use >>=). By induction you will have to perform all the actions in the list (which takes forever when the list is infinitely long) before you can return a result.
unsafeInterleaveIO resolves this, but is unsafe.
mysteryFilter f [] = return []
mysteryFilter f (x:xs) = do ys <- unsafeInterleaveIO $ mysteryFilter f xs
y <- x
if f y then return (y:ys) else return ys
the problem is that this breaks the sequence that the monad is supposed to provide. You no longer have guarantees about when your monadic actions happen (they might never happen, they might happen multiple times, etc).
Lists just do not play nice with IO. This is why we have the plethora of streaming types (Iteratees, Conduits, Pipes, etc).
The simplest such type is probably
data MList m a = Nil | Cons a (m (MList m a))
note that we observe that
[a] == MList Id a
since
toMList :: [a] -> MList Id a
toMList [] = Nil
toMList (x:xs) = Cons x $ return $ toMList xs
fromMList :: MList Id a -> [a]
fromMList Nil = []
fromMList (Cons x xs) = x:(fromMList . runId $ xs)
also, MList is a functor
instance Functor m => Functor (MList m) where
fmap f Nil = Nil
fmap f (Cons x xs) = Cons (f x) (fmap (fmap f) xs)
and it is a functor in the category of Functor's and Natural transformations.
trans :: Functor m => (forall x. m x -> n x) -> MList m a -> MList n a
trans f Nil = Nil
trans f (Cons x xs) = Cons x (f (fmap trans f xs))
with this it is easy to write what you want
mysteryFilter :: (a -> Bool) -> MList IO (IO a) -> IO (MList IO a)
mysteryFilter f Nil = return Nil
mysteryFilter f (Cons x xs)
= do y <- x
let ys = liftM (mysteryFilter f) xs
if f y then Cons y ys else ys
or various other similar functions.

Resources