Inconsistent do notation in functions - haskell

Why is this function allowed:
-- function 1
myfunc :: String
myfunc = do
x <- (return True)
show x
and this is not:
-- function 2
myfunc :: String
myfunc = do
x <- getLine
show x
The compile error:
Couldn't match type `[]' with `IO'
Expected type: IO Char
Actual type: String
I get why function 2 shouldn't work, but why then thus function 1 work?
and why does this then work:
-- function 3
myfunc = do
x <- getLine
return (show x)
I get that it returns IO String then, but why is function 1 also not forced to do this?

In function1 the do block in myfunc is working in the list monad, because String is really just [Char]. In there, return True just creates [True]. When you do x <- return True that "extracts" True out of [True] and binds it to x. The next line show x converts True into a String "True". which being the return value the compiler value expects to see, ends up working fine.
Meanwhile in function2, the do block in myfunc is also working on the list monad (for the same reason, String being really [Char]) but calls on getLine which is only available in the IO monad. So unsurprisingly, this fails.
-- EDIT 1
OP has added a function3
-- function 3
myfunc :: String
myfunc = do
x <- getLine
return (show x)
No this should not work for the same reason function2 fails.
-- EDIT 2
OP has updated function3 to fix a copy paste error.
-- function 3
myfunc = do
x <- getLine
return (show x)
This is mentioned in the comments, but for clarity sake, this works because, when the type information is unspecified, GHC makes it best inference and after seeing getLine, it figures it’s IO String which does provide getLine.
Note - I wrote this answer with as casual a tone as I could manage without being wrong with the intention of making it approachable to a beginner level.

do blocks work in the context of an arbitrary Monad. The Monad, in this case, is []. The Monad instance for lists is based on list comprehensions:
instance Monad [] where
return x = [x]
xs >>= f = [y | x <- xs, y <- f x]
You can desugar the do notation thus:
myfunc :: String
myfunc = do
x <- (return True)
show x
-- ==>
myfunc = [y | x <- return True, y <- show x]
-- ==>
myfunc = [y | x <- [True], y <- show x]
In a list comprehension, x <- [True] is really just the same as let x = True, because you're only drawing one element from the list. So
myfunc = [y | y <- show True]
Of course, "the list of all y such that y is in show True" is just show True.

Related

How to randomly shuffle a list

I have random number generator
rand :: Int -> Int -> IO Int
rand low high = getStdRandom (randomR (low,high))
and a helper function to remove an element from a list
removeItem _ [] = []
removeItem x (y:ys) | x == y = removeItem x ys
| otherwise = y : removeItem x ys
I want to shuffle a given list by randomly picking an item from the list, removing it and adding it to the front of the list. I tried
shuffleList :: [a] -> IO [a]
shuffleList [] = []
shuffleList l = do
y <- rand 0 (length l)
return( y:(shuffleList (removeItem y l) ) )
But can't get it to work. I get
hw05.hs:25:33: error:
* Couldn't match expected type `[Int]' with actual type `IO [Int]'
* In the second argument of `(:)', namely
....
Any idea ?
Thanks!
Since shuffleList :: [a] -> IO [a], we have shuffleList (xs :: [a]) :: IO [a].
Obviously, we can't cons (:) :: a -> [a] -> [a] an a element onto an IO [a] value, but instead we want to cons it onto the list [a], the computation of which that IO [a] value describes:
do
y <- rand 0 (length l)
-- return ( y : (shuffleList (removeItem y l) ) )
shuffled <- shuffleList (removeItem y l)
return y : shuffled
In do notation, values to the right of <- have types M a, M b, etc., for some monad M (here, IO), and values to the left of <- have the corresponding types a, b, etc..
The x :: a in x <- mx gets bound to the pure value of type a produced / computed by the M-type computation which the value mx :: M a denotes, when that computation is actually performed, as a part of the combined computation represented by the whole do block, when that combined computation is performed as a whole.
And if e.g. the next line in that do block is y <- foo x, it means that a pure function foo :: a -> M b is applied to x and the result is calculated which is a value of type M b, denoting an M-type computation which then runs and produces / computes a pure value of type b to which the name y is then bound.
The essence of Monad is thus this slicing of the pure inside / between the (potentially) impure, it is these two timelines going on of the pure calculations and the potentially impure computations, with the pure world safely separated and isolated from the impurities of the real world. Or seen from the other side, the pure code being run by the real impure code interacting with the real world (in case M is IO). Which is what computer programs must do, after all.
Your removeItem is wrong. You should pick and remove items positionally, i.e. by index, not by value; and in any case not remove more than one item after having picked one item from the list.
The y in y <- rand 0 (length l) is indeed an index. Treat it as such. Rename it to i, too, as a simple mnemonic.
Generally, with Haskell it works better to maximize the amount of functional code at the expense of non-functional (IO or randomness-related) code.
In your situation, your “maximum” functional component is not removeItem but rather a version of shuffleList that takes the input list and (as mentioned by Will Ness) a deterministic integer position. List function splitAt :: Int -> [a] -> ([a], [a]) can come handy here. Like this:
funcShuffleList :: Int -> [a] -> [a]
funcShuffleList _ [] = []
funcShuffleList pos ls =
if (pos <=0) || (length(take (pos+1) ls) < (pos+1))
then ls -- pos is zero or out of bounds, so leave list unchanged
else let (left,right) = splitAt pos ls
in (head right) : (left ++ (tail right))
Testing:
λ>
λ> funcShuffleList 4 [0,1,2,3,4,5,6,7,8,9]
[4,0,1,2,3,5,6,7,8,9]
λ>
λ> funcShuffleList 5 "#ABCDEFGH"
"E#ABCDFGH"
λ>
Once you've got this, you can introduce randomness concerns in simpler fashion. And you do not need to involve IO explicitely, as any randomness-friendly monad will do:
shuffleList :: MonadRandom mr => [a] -> mr [a]
shuffleList [] = return []
shuffleList ls =
do
let maxPos = (length ls) - 1
pos <- getRandomR (0, maxPos)
return (funcShuffleList pos ls)
... IO being just one instance of MonadRandom.
You can run the code using the default IO-hosted random number generator:
main = do
let inpList = [0,1,2,3,4,5,6,7,8]::[Integer]
putStrLn $ "inpList = " ++ (show inpList)
-- mr automatically instantiated to IO:
outList1 <- shuffleList inpList
putStrLn $ "outList1 = " ++ (show outList1)
outList2 <- shuffleList outList1
putStrLn $ "outList2 = " ++ (show outList2)
Program output:
$ pickShuffle
inpList = [0,1,2,3,4,5,6,7,8]
outList1 = [6,0,1,2,3,4,5,7,8]
outList2 = [8,6,0,1,2,3,4,5,7]
$
$ pickShuffle
inpList = [0,1,2,3,4,5,6,7,8]
outList1 = [4,0,1,2,3,5,6,7,8]
outList2 = [2,4,0,1,3,5,6,7,8]
$
The output is not reproducible here, because the default generator is seeded by its launch time in nanoseconds.
If what you need is a full random permutation, you could have a look here and there - Knuth a.k.a. Fisher-Yates algorithm.

When can I rely on Haskell to read a list lazily?

Why do I get an infinite loop (<<loop>>) runtime error here?
file feedback.hs:
plus1 :: [Int]->[Int] -- add 1 to input stream
plus1 [] = []
plus1 (x:xs) = (x+1): plus1 xs
to10 :: [Int] -> [Int] -- stop the input stream when it gets to 10
to10 (x:xs) | x < 10 = x : to10 xs
| otherwise = []
to10plus :: [Int] -> ([Int], Int) -- like to10 but also return the count
to10plus (x:xs) | x < 10 = (x, 1) `merge` (to10plus xs)
| otherwise = ([], 0)
where merge (a, b) (as, bs) = (a:as, b+bs)
main = do
let out = plus1 $ 1: to10 out
putStrLn $ show out -- gives [2,3,4,5,6,7,8,9,10]
let out = plus1 $ 1: out2
out2 = to10 out
putStrLn $ show out -- same as above
let out = plus1 $ 1: out2
(out2, count) = to10plus out
putStrLn $ show (out, count) -- expect ([2,3,4,5,6,7,8,9,10], 8)
-- but get runtime error: <<loop>>
$ ghc feedback.hs
[1 of 1] Compiling Main ( feedback.hs, feedback.o )
Linking feedback ...
$ ./feedback
[2,3,4,5,6,7,8,9,10]
[2,3,4,5,6,7,8,9,10]
feedback: <<loop>>
You can fix to10plus by using an irrefutable match (i.e., a ~ prefix) in your definition of merge:
merge (a, b) ~(as, bs) = (a:as, b+bs)
The reason for the difference in behavior between to10 and to10plus is that to10 can return the first element of the list without having to evaluate to10 xs and so without inspecting xs.
In contrast, before it can return anything, to10plus must successfully call merge with the arguments (x, 1) and to10plus xs. For this call to succeed, to10plus xs must be evaluated far enough to ensure it matches the pattern (as, bs) used in the definition of merge, but that evaluation requires inspecting elements of xs, which aren't available yet.
You could also have avoided the problem by defining to10plus a little differently:
to10plus (x:xs) | x < 10 = (x:as,1+bs)
| otherwise = ([], 0)
where (as,bs) = to10plus xs
Here, to10plus can provide the first element x of the first part of the tuple without trying to evaluate as, and so without trying to pattern match to10plus xs with (as,bs) in the where clause. A let clause would have done the same thing:
to10plus (x:xs) | x < 10 = let (as,bs) = to10plus xs in (x:as,1+bs)
| otherwise = ([], 0)
As #luqui points out, this is a difference in the timing for pattern matches made by let and where statements:
let (a,b) = expr in body
-- OR --
body where (a,b) = expr
versus case statements / function definitions:
case expr of (a,b) -> body
-- OR --
f (a,b) = body -- AND THEN EVALUATING: -- f expr
The let and where statements match patterns lazily, meaning that expr isn't matched to the pattern (a,b) until a or b are evaluated in the body. In contrast, for the case statement, expr is matched to (a,b) right away, before the body is even examined. And given the above definition for f, the argument to f will be matched to (a,b) as soon as the expression f expr is evaluated without waiting until a or b is needed in the function body. Here are some working examples to illustrate:
ex1 = let (a,b) = undefined in print "okay"
ex2 = print "also okay" where (a,b) = undefined
ex3 = case undefined of (a,b) -> print "not okay"
ex4 = f undefined
f (a,b) = print "also not okay"
main = do
ex1 -- works
ex2 -- works
ex3 -- fails
ex4 -- fails
Adding ~ changes the behavior for case / function definitions so the matching takes place only when a or b are needed:
ex5 = case undefined of ~(a,b) -> print "works fine"
ex6 = g undefined
g ~(a,b) = print "also works fine"
ex7 = case undefined of ~(a,b) -> print $ "But trying " ++ show (a+b) ++ " would fail"

How do I recursively use newStdGen in Haskell? (to get different random results on each iteration)

I use System.Random and System.Random.Shuffle to shuffle the order of characters in a string, I shuffle it using:
shuffle' string (length string) g
g being a getStdGen.
Now the problem is that the shuffle can result in an order that's identical to the original order, resulting in a string that isn't really shuffled, so when this happens I want to just shuffle it recursively until it hits a a shuffled string that's not the original string (which should usually happen on the first or second try), but this means I need to create a new random number generator on each recursion so it wont just shuffle it exactly the same way every time.
But how do I do that? Defining a
newg = newStdGen
in "where", and using it results in:
Jumble.hs:20:14:
Could not deduce (RandomGen (IO StdGen))
arising from a use of shuffle'
from the context (Eq a)
bound by the inferred type of
shuffleString :: Eq a => IO StdGen -> [a] -> [a]
at Jumble.hs:(15,1)-(22,18)
Possible fix:
add an instance declaration for (RandomGen (IO StdGen))
In the expression: shuffle' string (length string) g
In an equation for `shuffled':
shuffled = shuffle' string (length string) g
In an equation for `shuffleString':
shuffleString g string
= if shuffled == original then
shuffleString newg shuffled
else
shuffled
where
shuffled = shuffle' string (length string) g
original = string
newg = newStdGen
Jumble.hs:38:30:
Couldn't match expected type `IO StdGen' with actual type `StdGen'
In the first argument of `jumble', namely `g'
In the first argument of `map', namely `(jumble g)'
In the expression: (map (jumble g) word_list)
I'm very new to Haskell and functional programming in general and have only learned the basics, one thing that might be relevant which I don't know yet is the difference between "x = value", "x <- value", and "let x = value".
Complete code:
import System.Random
import System.Random.Shuffle
middle :: [Char] -> [Char]
middle word
| length word >= 4 = (init (tail word))
| otherwise = word
shuffleString g string =
if shuffled == original
then shuffleString g shuffled
else shuffled
where
shuffled = shuffle' string (length string) g
original = string
jumble g word
| length word >= 4 = h ++ m ++ l
| otherwise = word
where
h = [(head word)]
m = (shuffleString g (middle word))
l = [(last word)]
main = do
g <- getStdGen
putStrLn "Hello, what would you like to jumble?"
text <- getLine
-- let text = "Example text"
let word_list = words text
let jumbled = (map (jumble g) word_list)
let output = unwords jumbled
putStrLn output
This is pretty simple, you know that g has type StdGen, which is an instance of the RandomGen typeclass. The RandomGen typeclass has the functions next :: g -> (Int, g), genRange :: g -> (Int, Int), and split :: g -> (g, g). Two of these functions return a new random generator, namely next and split. For your purposes, you can use either quite easily to get a new generator, but I would just recommend using next for simplicity. You could rewrite your shuffleString function to something like
shuffleString :: RandomGen g => g -> String -> String
shuffleString g string =
if shuffled == original
then shuffleString (snd $ next g) shuffled
else shuffled
where
shuffled = shuffle' string (length string) g
original = string
End of answer to this question
One thing that might be relevant which I don't know yet is the difference between "x = value", "x <- value", and "let x = value".
These three different forms of assignment are used in different contexts. At the top level of your code, you can define functions and values using the simple x = value syntax. These statements are not being "executed" inside any context other than the current module, and most people would find it pedantic to have to write
module Main where
let main :: IO ()
main = do
putStrLn "Hello, World"
putStrLn "Exiting now"
since there isn't any ambiguity at this level. It also helps to delimit this context since it is only at the top level that you can declare data types, type aliases, and type classes, these can not be declared inside functions.
The second form, let x = value, actually comes in two variants, the let x = value in <expr> inside pure functions, and simply let x = value inside monadic functions (do notation). For example:
myFunc :: Int -> Int
myFunc x =
let y = x + 2
z = y * y
in z * z
Lets you store intermediate results, so you get a faster execution than
myFuncBad :: Int -> Int
myFuncBad x = (x + 2) * (x + 2) * (x + 2) * (x + 2)
But the former is also equivalent to
myFunc :: Int -> Int
myFunc x = z * z
where
y = x + 2
z = y * y
There are subtle difference between let ... in ... and where ..., but you don't need to worry about it at this point, other than the following is only possible using let ... in ..., not where ...:
myFunc x = (\y -> let z = y * y in z * z) (x + 2)
The let ... syntax (without the in ...) is used only in monadic do notation to perform much the same purpose, but usually using values bound inside it:
something :: IO Int
something = do
putStr "Enter an int: "
x <- getLine
let y = myFunc (read x)
return (y * y)
This simply allows y to be available to all proceeding statements in the function, and the in ... part is not needed because it's not ambiguous at this point.
The final form of x <- value is used especially in monadic do notation, and is specifically for extracting a value out of its monadic context. That may sound complicated, so here's a simple example. Take the function getLine. It has the type IO String, meaning it performs an IO action that returns a String. The types IO String and String are not the same, you can't call length getLine, because length doesn't work for IO String, but it does for String. However, we frequently want that String value inside the IO context, without having to worry about it being wrapped in the IO monad. This is what the <- is for. In this function
main = do
line <- getLine
print (length line)
getLine still has the type IO String, but line now has the type String, and can be fed into functions that expect a String. Whenever you see x <- something, the something is a monadic context, and x is the value being extracted from that context.
So why does Haskell have so many different ways of defining values? It all comes down to its type system, which tries really hard to ensure that you can't accidentally launch the missiles, or corrupt a file system, or do something you didn't really intend to do. It also helps to visually separate what is an action, and what is a computation in source code, so that at a glance you can tell if an action is being performed or not. It does take a while to get used to, and there are probably valid arguments that it could be simplified, but changing anything would also break backwards compatibility.
And that concludes today's episode of Way Too Much Information(tm)
(Note: To other readers, if I've said something incorrect or potentially misleading, please feel free to edit or leave a comment pointing out the mistake. I don't pretend to be perfect in my descriptions of Haskell syntax.)

Non-exhaustive patterns in lambda

I am getting Non-exhaustive patterns in lambda. I am not sure of the cause yet. Please anyone how to fix it. The code is below:
import Control.Monad
import Data.List
time_spent h1 h2 = max (abs (fst h1 - fst h2)) (abs (snd h1 - snd h2))
meeting_point xs = foldl' (find_min_time) maxBound xs
where
time_to_point p = foldl' (\tacc p' -> tacc + (time_spent p p')) 0 xs
find_min_time min_time p = let x = time_to_point p in if x < min_time then x else min_time
main = do
n <- readLn :: IO Int
points <- fmap (map (\[x,y] -> (x,y)) . map (map (read :: String->Int)) . map words . lines) getContents
putStrLn $ show $ meeting_point points
This is the lambda with the non-exhaustive patterns: \[x,y] -> (x,y).
The non-exhaustive pattern is because the argument you've specified, [x,y] doesn't match any possible list - it only matches lists with precisely two elements.
I would suggest replacing it with a separate function with an error case to print out the unexpected data in an error message so you can debug further, e.g.:
f [x,y] = (x, y)
f l = error $ "Unexpected list: " ++ show l
...
points <- fmap (map f . map ...)
As an addition to #GaneshSittampalam's answer, you could also do this with more graceful error handling using the Maybe monad, the mapM function from Control.Monad, and readMaybe from Text.Read. I would also recommend refactoring your code so that the parsing is its own function, it makes your main function much cleaner and easier to debug.
import Control.Monad (mapM)
import Text.Read (readMaybe)
toPoint :: [a] -> Maybe (a, a)
toPoint [x, y] = Just (x, y)
toPoint _ = Nothing
This is just a simple pattern matching function that returns Nothing if it gets a list with length not 2. Otherwise it turns it into a 2-tuple and wraps it in Just.
parseData :: String -> Maybe [(Int, Int)]
parseData text = do
-- returns Nothing if a non-Int is encountered
values <- mapM (mapM readMaybe . words) . lines $ text
-- returns Nothing if a line doesn't have exactly 2 values
mapM toPoint values
Your parsing can actually be simplified significantly by using mapM and readMaybe. The type of readMaybe is Read a => String -> Maybe a, and in this case since we've specified the type of parseData to return Maybe [(Int, Int)], the compiler can infer that readMaybe should have the local type of String -> Maybe Int. We still use lines and words in the same way, but now since we use mapM the type of the right hand side of the <- is Maybe [[Int]], so the type of values is [[Int]]. What mapM also does for us is if any of those actions fails, the overall computation exits early with Nothing. Then we simply use mapM toPoint to convert values into a list of points, but also with the failure mechanism built in. We actually could use the more general signature of parseData :: Read a => String -> Maybe [(a, a)], but it isn't necessary.
main = do
n <- readLn :: IO Int
points <- fmap parseData getContents
case points of
Just ps -> print $ meeting_point ps
Nothing -> putStrLn "Invalid data!"
Now we just use fmap parseData on getContents, making points have the type Maybe [(Int, Int)]. Finally, we pattern match on points to print out the result of the meeting_point computation or print a helpful message if something went wrong.
If you wanted even better error handling, you could leverage the Either monad in a similar fashion:
toPoint :: [a] -> Either String (a, a)
toPoint [x, y] = Right (x, y)
toPoint _ = Left "Invalid number of points"
readEither :: Read a => String -> Either String a
readEither text = maybe (Left $ "Invalid parse: " ++ text) Right $ readMaybe text
-- default value ^ Wraps output on success ^
-- Same definition with different type signature and `readEither`
parseData :: String -> Either String [(Int, Int)]
parseData text = do
values <- mapM (mapM readEither . words) . lines $ text
mapM toPoint values
main = do
points <- fmap parseData getContents
case points of
Right ps -> print $ meeting_point ps
Left err -> putStrLn $ "Error: " ++ err

Pretty printing a syntax tree in Haskell

I don't understand this type error:
Couldn't match expected type `[t0]' with actual type `IO ()'
In the return type of a call of `printv'
In a stmt of a 'do' expression: px <- printv x
In the expression:
do { px <- printv x;
sep <- print ", ";
rest <- prints xs;
return (px : sep : rest) }
From:
data Value = IntValue Int
| TruthValue Bool
deriving (Eq, Show)
printv :: Value -> IO()
printv (IntValue i) = print i
printv (TruthValue b) = print ("boolean" ++ show b)
prints :: [Value] -> [IO()]
prints [] = []
prints (x:xs) = do px <- printv x
sep <- print ", "
rest <- prints xs
return (px:sep:rest)
It looks to me like every element (px) is converted into an IO() action, and then that is added to a list of the same things, thus producing an [IO()] list.
What am I missing here? Converting it to a list of strings, by removing the print's, works fine.
You're missing the return on the [] case of prints:
prints [] = return []
However, your prints is very strange. It returns a [()], because print is outputting strings to the console, not returning them.
Do you mean to return strings from your printv function?
Since you're trying to pretty print a syntax tree, here's roughly the right way to do it:
Use pretty-printing combinators
Use a pretty typeclass
Like so:
import Text.PrettyPrint
import Data.List
data Value
= VInt Int
| VBool Bool
deriving (Eq, Show)
class Pretty a where
pretty :: a -> Doc
instance Pretty Value where
pretty (VInt i) = int i
pretty (VBool b) = text "Boolean" <+> text (show b)
draw :: [Value] -> String
draw = intercalate ", " . map (render.pretty)
main = putStrLn $ draw [VInt 7, VBool True, VInt 42]
Running it:
*A> main
7, Boolean True, 42
Take a closer look at the type of your function:
prints :: [Value] -> [IO()]
But if we now take a look at prints [] = [], this can't match, because the type of that one is
prints :: [t] -> [a]
Therefore, you missed using prints [] = return [], to make it work.
If you're not evaluating an IO action, you don't need a do block. Just treat IO () as a normal type.
prints (x:xs) = printv x : print ", " : prints xs
You don't want prints to return an array of IO actions. You want it to return a single IO action that represents each of the IO actions bound together. Something like:
prints xs = mapM_ (\x -> printv x >> putStr ", ") xs
Except that I don't think the new lines are going to end up where you want them.
Look at the documentation for mapM and sequence for more information. In particular, the implementation of sequence is probably similar to what you're trying to do.
However, I would really recommend that instead doing all the work in an IO function, you should write a pure function to render the textual format you want, and then just print that. In particular, it seems that an instance of Show for Value would be appropriate.
instance Show Value where
show (IntValue i) = show i
show (TruthValue b) = "boolean " ++ show b
That way you can just call print value rather than printv value, and if you really wanted to you could define prints as follows.
import Data.List
prints :: (Show a) => [a] -> IO ()
prints = putStrLn . intercalate ", " . map show`.

Resources