spanM, takeWhileM in Haskell - haskell

I have following problem: Given a [String] and String->IO Int. So I can make a transformation (map) and get [IO Int]. Now, I have to do two things -- perfrorm that actions, from start, until result is positive and I need to know, was all list processed.
I am forbidded to process after first non-positive result.
takeWhileM do not answer second question(length compraison is too impractical), and spanM perform forbidden IO.
Of course, I can write recursive function myself, but I want to do it in Haskell way, with all good of high-order functions.
Suggestions? Probably, use completely another approach?
Task above is a bit simplified task from my project.

You can use allM from the monad-loops package:
Prelude Control.Monad.Loops> let xs = ["a", "bb", "ccc", "dddd", "eeeee"]
Prelude Control.Monad.Loops> let f x = putStrLn x >> return (length x)
Prelude Control.Monad.Loops> let p x = x < 2
Prelude Control.Monad.Loops> allM (fmap p . f) xs
a
bb
False
There's also an allM in Control.Monad.ListM, but it's not appropriately lazy—it will continue to perform computations after you hit a positive result.
(I'm with you on this, by the way—I hate writing one-off recursive functions.)

I'm not familiar with the functions takeWhileM and spanM (and neither is hoogle) (edit: as per comment, they can be found in Control.Monad.ListM).
Given that, I think the best thing for you to do is to make a one-off function to perform this task. If it later turns out that you need to write code to do something similar, then you can factor out the common parts and re-use them. There's nothing wrong with writing one-off code in general, it's code duplication that's bad.
There are a few ways to write the function you want - one possible way is like this:
process :: [IO Int] -> IO Bool
process [] = return True
process [a] = a >> return True
process (a:as) = do
n <- a
if n > 0
then return False
else process as

#illusionoflife: I don't see how using takeWhileM would improve on #Chris's solution.
For example:
import Control.Monad.ListM
process :: [IO Int] -> IO Bool
process as = do
taken <- takeWhileM (>>= return . (<= 0)) as
return (length taken >= length as - 1)
(Code not verified!)
#Chris's looks more readable, among other things because in his solution we don't need to figure out if we should use >= or ==. Besides, since I call length we can't use it on an infinite input list.

Related

Is it recommended to use recursive IO actions in the tail recursive form?

Consider the two following variations:
myReadListTailRecursive :: IO [String]
myReadListTailRecursive = go []
where
go :: [String] -> IO [String]
go l = do {
inp <- getLine;
if (inp == "") then
return l;
else go (inp:l);
}
myReadListOrdinary :: IO [String]
myReadListOrdinary = do
inp <- getLine
if inp == "" then
return []
else
do
moreInps <- myReadListOrdinary
return (inp:moreInps)
In ordinary programming languages, one would know that the tail recursive variant is a better choice.
However, going through this answer, it is apparent that haskell's implementation of recursion is not similar to that of using the recursion stack repeatedly.
But because in this case the program in question involves actions, and a strict monad, I am not sure if the same reasoning applies. In fact, I think in the IO case, the tail recursive form is indeed better. I am not sure how to correctly reason about this.
EDIT: David Young pointed out that the outermost call here is to (>>=). Even in that case, does one of these styles have an advantage over the other?
FWIW, I'd go for existing monadic combinators and focus on readability/consiseness. Using unfoldM :: Monad m => m (Maybe a) -> m [a]:
import Control.Monad (liftM, mfilter)
import Control.Monad.Loops (unfoldM)
myReadListTailRecursive :: IO [String]
myReadListTailRecursive = unfoldM go
where
go :: IO (Maybe String)
go = do
line <- getLine
return $ case line of
"" -> Nothing
s -> Just s
Or using MonadPlus instance of Maybe, with mfilter :: MonadPlus m => (a -> Bool) -> m a -> m a:
myReadListTailRecursive :: IO [String]
myReadListTailRecursive = unfoldM (liftM (mfilter (/= "") . Just) getLine)
Another, more versatile option, might be to use LoopT.
That’s really not how I would write it, but it’s clear enough what you’re doing. (By the way, if you want to be able to efficiently insert arbitrary output from any function in the chain, without using monads, you might try a Data.ByteString.Builder.)
Your first implementation is very similar to a left fold, and your second very similar to a right fold or map. (You might try actually writing them as such!) The second one has several advantages for I/O. One of the most important, for handling input and output, is that it can be interactive.
You’ll notice that the first builds the entire list from the outside in: in order to determine what the first element of the list is, the program needs to compute the entire structure to get to the innermost thunk, which is return l. The program generates the entire data structure first, then starts to process it. That’s useful when you’re reducing a list, because tail-recursive functions and strict left folds are efficient.
With the second, the outermost thunk contains the head and tail of the list, so you can grab the tail, then call the thunk to generate the second list. This can work with infinite lists, and it can produce and return partial results.
Here’s a contrived example: a program that reads in one integer per line and prints the sums so far.
main :: IO ()
main = interact( display . compute 0 . parse . lines )
where parse :: [String] -> [Int]
parse [] = []
parse (x:xs) = (read x):(parse xs)
compute :: Int -> [Int] -> [Int]
compute _ [] = []
compute accum (x:xs) = let accum' = accum + x
in accum':(compute accum' xs)
display = unlines . map show
If you run this interactively, you’ll get something like:
$ 1
1
$ 2
3
$ 3
6
$ 4
10
But you could also write compute tail-recursively, with an accumulating parameter:
main :: IO ()
main = interact( display . compute [] . parse . lines )
where parse :: [String] -> [Int]
parse = map read
compute :: [Int] -> [Int] -> [Int]
compute xs [] = reverse xs
compute [] (y:ys) = compute [y] ys
compute (x:xs) (y:ys) = compute (x+y:x:xs) ys
display = unlines . map show
This is an artificial example, but strict left folds are a common pattern. If, however, you write either compute or parse with an accumulating parameter, this is what you get when you try to run interactively, and hit EOF (control-D on Unix, control-Z on Windows) after the number 4:
$ 1
$ 2
$ 3
$ 4
1
3
6
10
This left-folded version needs to compute the entire data structure before it can read any of it. That can’t ever work on an infinite list (When would you reach the base case? How would you even reverse an infinite list if you did?) and an application that can’t respond to user input until it quits is a deal-breaker.
On the other hand, the tail-recursive version can be strict in its accumulating parameter, and will run more efficiently, especially when it’s not being consumed immediately. It doesn’t need to keep any thunks or context around other than its parameters, and it can even re-use the same stack frame. A strict accumulating function, such as Data.List.foldl', is a great choice whenver you’re reducing a list to a value, not building an eagerly-evaluated list of output. Functions such as sum, product or any can’t return any useful intermediate value. They inherently have to finish the computation first, then return the final result.

Write factorial as imperative function using Haskell

I have written the following code in Haskell:
import Data.IORef
import Control.Monad
import Control.Monad.Trans.Cont
import Control.Monad.IO.Class
fac n = do
i<-newIORef 1
f<-newIORef 1
replicateM_ n $ do
ri<-readIORef i
modifyIORef f (\x->x*ri)
modifyIORef i (+1)
readIORef f
This is very nice code which implements factorial as an imperative function. But replicateM_ cannot fully simulate the use of a real for loop. So I tried to create something using continuations but I have failed here is my code:
ff = (`runContT` id) $ do
callCC $ \exit1 -> do
liftIO $ do
i<-newIORef 1
f<-newIORef 1
callCC $ \exit2 -> do
liftIO $ do
ri<-readIORef i
modifyIORef (\x->x*ri)
modifyIORef i (+1)
rri<-readIORef i
when (rri<=n) $ exit2(())
liftIO $ do
rf<-readIORef f
return rf
Can you help me correct my code?
Thanks
Since your a beginner to Haskell and not doing this simply to learn how continuations and IORefs work, you're doing it wrong.
The Haskell-y way to write an imperative loop is tail-calls or folds.
factorial n = foldl1' (*) [1..n]
factorial' n = go 1 n
where go accum 0 = accum
go accum n = go (n-1) (accum * n)
Also since Haskell's callCC in essence provides you an early return, using it to simulate loops is not going to work.
callCC (\c -> ???)
Think about what we would have to put in for ??? in order to loop. somehow, we want to run callCC again if it returns a certain value, otherwise just keep going on our merry way.
But nothing we put in ??? can make the callCC run again! It's going to return a value no matter what we do. So instead we'll need to do something around that callCC
let (continue, val) = callCC (someFunc val)
in if continue
then callCallCCAgain val
else val
Something like this right? But wait, callCallCCAgain is recursion! It's even tail recursion! In fact, that callCC is doing no one any good
loop val = let (continue, val') = doBody val
in if continue
then loop val'
else val'
Look familiar? This is the same structure as factorial' above.
You can still use IORefs and something like the monad-loops package, but it's going to be an uphill battle always because Haskell isn't meant to be written like that.
Summary
When you want to directly do "loops" in haskell, use tail recursion. But really, try to use combinators like fold and map, they're like little specialized loops and GHC is fantastic at optimizing them. And definitely don't use IORefs, trying to program Haskell like it's C is just going to hurt your performance, readability, and everyone will be sad.

Haskell monad: IO [Double] to [IO Double]

Consider the following code that is supposed to print out random numbers:
import System.Random.Mersenne
main =
do g <- (newMTGen Nothing)
xs <- (randoms g) :: IO [Double]
mapM_ print xs
When run, I get a segmentation fault error. That is unsurprising, since the function 'randoms' produces an infinite list. Suppose I wanted to print out only the first ten values of xs. How could I do that? xs has type IO [Double], and I think I want a variable of type [IO Double]. What operators exist to convert between the two.
If you get a segmentation fault error, and you didn't use the FFI or any functions with unsafe in their name, that's not unsurprising, in any situation! It means there's a bug with either GHC, or a library you're using is doing something unsafe.
Printing out an infinite list of Doubles with mapM_ print is perfectly fine; the list will be processed incrementally and the program should run with constant memory usage. I suspect there is a bug in the System.Random.Mersenne module you're using, or a bug the C library it's based on, or a problem with your computer (such as faulty RAM).1 Note that newMTGen comes with this warning:
Due to the current SFMT library being vastly impure, currently only a single generator is allowed per-program. Attempts to reinitialise it will fail.
You might be better off using the provided global MTGen instead.
That said, you can't convert IO [Double] into [IO Double] in that way; there's no way to know how long the resulting list would be without executing the IO action, which is impossible, since you have a pure result (albeit one that happens to contain IO actions). For infinite lists, you could write:
desequence :: IO [a] -> [IO a]
desequence = desequence' 0
where
desequence n m = fmap (!! n) m : desequence (n+1) m
But every time you execute an action in this list, the IO [a] action would be executed again; it'd just discard the rest of the list.
The reason randoms can work and return an infinite list of random numbers is because it uses lazy IO with unsafeInterleaveIO. (Note that, despite the "unsafe" in the name, this one can't cause segfaults, so something else is afoot.)
1 Other, less likely possibilities include a miscompilation of the C library, or a bug in GHC.
Suppose I wanted to print out only the first ten values of xs. How could I do that?
Just use take:
main =
do g <- (newMTGen Nothing)
xs <- (randoms g) :: IO [Double]
mapM_ print $ take 10 xs
You wrote
xs has type IO [Double]
But actually, randoms g has type IO [Double], but thanks to the do notation, xs has type [Double], you can just apply take 10 to it.
You could also skip the binding using liftM:
main =
do g <- newMTGen Nothing
ys <- liftM (take 10) $ randoms g :: IO [Double]
mapM_ print ys

Dice Game in Haskell

I'm trying to spew out randomly generated dice for every roll that the user plays. The user has 3 rolls per turn and he gets to play 5 turns (I haven't implemented this part yet and I would appreciate suggestions).
I'm also wondering how I can display the colors randomly. I have the list of tuples in place, but I reckon I need some function that uses random and that list to match those colors. I'm struggling as to how.
module Main where
import System.IO
import System.Random
import Data.List
diceColor = [("Black",1),("Green",2),("Purple",3),("Red",4),("White",5),("Yellow",6)]
{-
randomList :: (RandomGen g) -> Int -> g -> [Integer]
random 0 _ = []
randomList n generator = r : randomList (n-1) newGenerator
where (r, newGenerator) = randomR (1, 6) generator
-}
rand :: Int -> [Int] -> IO ()
rand n rlst = do
num <- randomRIO (1::Int, 6)
if n == 0
then doSomething rlst
else rand (n-1) (num:rlst)
doSomething x = putStrLn (show (sort x))
main :: IO ()
main = do
--hSetBuffering stdin LineBuffering
putStrLn "roll, keep, score?"
cmd <- getLine
doYahtzee cmd
--rand (read cmd) []
doYahtzee :: String -> IO ()
doYahtzee cmd = do
if cmd == "roll"
then rand 5 []
else do print "You won"
There's really a lot of errors sprinkled throughout this code, which suggests to me that you tried to build the whole thing at once. This is a recipe for disaster; you should be building very small things and testing them often in ghci.
Lecture aside, you might find the following facts interesting (in order of the associated errors in your code):
List is deprecated; you should use Data.List instead.
No let is needed for top-level definitions.
Variable names must begin with a lower case letter.
Class prerequisites are separated from a type by =>.
The top-level module block should mainly have definitions; you should associate every where clause (especially the one near randomList) with a definition by either indenting it enough not to be a new line in the module block or keeping it on the same line as the definition you want it to be associated with.
do introduces a block; those things in the block should be indented equally and more than their context.
doYahtzee is declared and used as if it has three arguments, but seems to be defined as if it only has one.
The read function is used to parse a String. Unless you know what it does, using read to parse a String from another String is probably not what you want to do -- especially on user input.
putStrLn only takes one argument, not four, and that argument has to be a String. However, making a guess at what you wanted here, you might like the (!!) and print functions.
dieRoll doesn't seem to be defined anywhere.
It's possible that there are other errors, as well. Stylistically, I recommend that you check out replicateM, randomRs, and forever. You can use hoogle to search for their names and read more about them; in the future, you can also use it to search for functions you wish existed by their type.

Haskell write String, easy question

writeStr []=putChar ' '
writeStr (x:xs) = (putChar x)(writeStr xs)
Hello, and thanks in advance, i get a type error, it should be a simple answer but i just dont get where the error is coming from.
Your code is a bit strange. If I got it right, you try to print a string. Your method is to put the first string, and than the second. But it's not possible in Haskell to combine two IO actions like this. Have a look in your tutorial again about this, here's hwo it could look like:
writeStr [] = return () -- you had putChar ' ',
writeStr (x:xs) = do putChar x -- but this would print a superfluous whtiespace
writeStr xs
If you want to do several things sequentially, either use the do-keyword or monadic combinators. Its very easy, just like this:
do action1
action2
action3
...
FUZxxl has answered the immediate question, but I'd like to expand on it with some more ways of writing "writeStr" to illustrate more about monads.
As delnan said in the comments, you can also write
writeStr [] = return ()
writeStr (x:xs) = putChar x >> writeStr xs
This is actually the "desugared" version of the "do" notation. The ">>" operator is used to daisy-chain monadic actions together. Its actually a specialised version of the "bind" operator, written ">>=". See this question for more details.
But when you look at this, it seems that all we are doing is applying "putChar" to each element in the argument list. There is already a function in the Prelude called "map" for doing this, so maybe we could write:
writeStr xs = map putChar xs
But when you try that it won't work. The reason becomes evident if you go into GHCi and type this:
:type map putChar "Hello"
[IO ()]
You want a single "IO()" action, but this gives you a list of them. What you need is a function that turns this list of IO actions into a single IO action. Fortunately one exists. The Prelude contains these two functions
sequence :: [IO a] -> IO [a]
sequence_ :: [IO a] -> IO ()
The first one is for when you want the list of results, the second is for cases where you don't, like this one. (Throughout this answer I'm going to be giving the IO-specific type signatures for clarity, but its important to remember that all these functions actually work for any monad.)
So now you can write:
writeStr xs = sequence_ $ map putChar xs
But there is a way of shortening this. Recall the "." operator, which sticks two functions together, and the way Haskell has of "currying" function arguments? We can rewrite the function above as:
writeStr = sequence_ . map putChar
This "point-free" style looks and feels very odd at first; it makes "writeStr" look more like a constant than a function. But it avoids the need to track variable names around the code when you are reading it, and so is often preferred. Its also a lot shorter and more readable when you are putting something complicated as the argument to "map" or similar higher order functions.
But we can go even shorter. The "sequence . map f" pattern is very common, so the "Control.Monad" module defines a couple more functions to embody it:
mapM :: (a -> IO b) -> [a] -> IO [b]
mapM f = sequence . map f
mapM_ :: (a -> IO b) -> [a] -> IO ()
mapM_ f = sequence_ . map f
So you can finally write
writeStr = mapM_ putChar

Resources