I m still learning haskell and i found a tutorial that introduces the IO concepts using the following hangman simple programm
import System.IO
import System.Random
main = do
handle <- openFile "enable1.txt" ReadMode
contents <- hGetContents handle
gen <- getStdGen
let words = map init (lines contents)
(n, _) = randomR(0, (length words) - 1) gen :: (Int, StdGen)
word = words !! n
play word (map (\x -> '_') word) 6
build the print the string
hClose handle
play word known guesses
| word == known = do
putStrLn known
putStrLn "You win!!"
| guesses == 0 = do
putStrLn known
putStrLn ("You lose. the word was " ++ word ++ ".")
| otherwise = do
putStrLn known
putStrLn ("You have " ++ guesses ++ "guesses left.")
line <- getLine
let (newKnown, newGuesses) = handle (head line) word known guesses
play word newKnown newGuesses
--putStrLn (handle (head line) word)
handle letter word known guesses
| letter `elem` word = (zipWith (\w k -> if w == letter then w else k) word known, guesses)
| otherwise = (known, guesses - 1)
enable1.txt is a local file that have lots of words.
I run the file using runhaskill
and i get the following error:
:~/Documents/atom/haskell$ runhaskell hangman.hs
hangman.hs:22:36: error:
• No instance for (Num [Char]) arising from the literal ‘6’
• In the third argument of ‘play’, namely ‘6’
In a stmt of a 'do' block: play word (map (\ x -> '_') word) 6
In the expression:
do { handle <- openFile "enable1.txt" ReadMode;
contents <- hGetContents handle;
gen <- getStdGen;
let words = map init (lines contents)
(n, _) = ...
....;
.... }
hangman.hs:30:16: error:
• No instance for (Num [Char]) arising from the literal ‘0’
• In the second argument of ‘(==)’, namely ‘0’
In the expression: guesses == 0
In a stmt of a pattern guard for
an equation for ‘play’:
guesses == 0
hangman.hs:37:36: error:
• No instance for (Num [Char]) arising from a use of ‘handle’
• In the expression: handle (head line) word known guesses
In a pattern binding:
(newKnown, newGuesses) = handle (head line) word known guesses
In the expression:
do { putStrLn known;
putStrLn ("You have " ++ guesses ++ "guesses left.");
line <- getLine;
let (newKnown, newGuesses) = handle (head line) word known guesses;
.... }
Can anyone please help me understand the issue/ how to fix it.
runhaskell --version is runghc 8.0.2
Others already pointed out some issues in your code. Here, I only wanted to provide you a general suggestion.
Most Haskellers, including "experts", always start writing any new top-level function (or binding, in general) from a type annotation. That is, by writing foo :: Type1 -> Type2 -> ... -> ReturnType. Indeed, this is strongly recommended for several reasons.
First, it helps the programmer focus their mind on what kind of data they have to process or produce. This might be obvious in the programmer's mind for simple programs, but it becomes less trivial in more serious, high-level code.
Second, it prevents the type inference engine to infer unintended types. Consider this code, for instance.
foo x = "hello" ++ x -- line A
This is accepted without problems, and x is inferred to be of type String by GHC.
However, in the programmer's mind x should have been an integer, and so, later on, the programmer writes
let s = foo 42 in ... -- line B
and GHC complains that 42 is not a String. Or even worse, that Num String can not be satisfied, meaning that a string in not a numeric type. Now the programmer is puzzled because GHC point to line B as the problem, but that code looks fine to the programmer. "I'm passing an integer, foo expects an integer, where is this weird string error coming from?!?"
This is not the compiler's fault -- it has no way of knowing that the code in line A was wrong. However, if the programmer told the compiler, around line A, that x was intended to be an integer, then it would indeed have been the compiler fault! The compiler should now complain about the error in line A! And indeed, it does: here's a GHCi quick test.
> foo :: Int -> String ; foo x = "hello" ++ x
error:
• Couldn't match expected type ‘[Char]’ with actual type ‘Int’
• In the second argument of ‘(++)’, namely ‘x’
In the expression: "hello" ++ x
In an equation for ‘foo’: foo x = "hello" ++ x
Ah-ha! ++ wants a string, but x is an integer. So we have to convert it
> foo :: Int -> String ; foo x = "hello" ++ show x
Now, no error arises.
In general, when coding and making some mistake, GHC might be led to infer unintended types, leading to puzzling errors later on, pointing to seeming perfect code. In such cases, a common technique is to add more and more type annotations, informing the compiler about the programmer's intent, so that GHC can produce more meaningful errors. Eventually, GHC and the programmer agree that something is wrong, and the bug can be fixed.
You are getting errors because the types are inconsistent in the program.
No instance for (Num X) means that "X is not any kind of number".
[Char] is the type of a string (String is an alias for it).
So your error means that something is being used as a string and as a number.
Looking over your code I can see that in play you have
"You have " ++ guesses ++ "guesses left." which means that guesses must be a string, in order to be concatenated with other strings.
guesses == 0 which means that guesses must be a number.
If you got this code from the tutorial, then it is a badly written tutorial and you should find a better one. If you wrote it yourself according to the tutorial, then you must have missed a step.
In order to convert a number to a string for printing, you can use the show function:
"You have " ++ show guesses ++ "guesses left."
You cannot (++) a String and a numeral type. You should first use function show to convert the number to a String before you can connect it with another string.
In your code, parameter word and known is of some type Num a => a, but (++) accepts only two String (i.e. [Char]) as a parameter (to be precise, it accept two lists of the same type of elements, and since you have already applied a String to it, the other parameter should also be a String). So you should replace word with show word, and the same for known.
Related
Sometimes the program shows an error if I don't use do. But it runs well without do sometimes.
ex:
countdown ::Int -> IO ()
countdown x = if x <= 0
then putStrLn "The End."
else putStrLn (show (x))
runs well
But
countdown ::Int -> IO ()
countdown x = if x <= 0
then putStrLn "The End."
else putStrLn (show (x))
countdown (x-1)
shows error
Short answer: line breaks don't mean "next statement" in Haskell, like they do in many mainstream languages, like Python, Ruby, and recently even JavaScript.
Long answer
First, let's get rid of the if. It only clouds the issue:
countdown1 :: Int -> IO ()
countdown1 x = putStrLn (show x)
countdown2 :: Int -> IO ()
countdown2 x = putStrLn (show x)
countdown (x-1)
Notice that the type of your function is IO (). That's the type of what the function must ultimately calculate. Or "produce", if you will. This means that whatever is on the right of the equality sign must be of type IO ().
countdown x = .........
^ ^
+-------+
\
the type of whatever is here must be `IO ()`
The first version, countdown1, does satisfy this, because the expression putStrLn (show x) is, indeed, of type IO ()
The second version, countdown2, on the other hand, looks very strange to the compiler. It looks like you're trying to call putStrLn, and you're trying to pass it three parameters: (show x), countdown, and (x-1).
Don't let the newline between (show x) and countdown confuse you: as mentioned above, newlines don't mean "next statement" in Haskell. This is because in Haskell there is no such thing as a "statement" in the first place. Everything is an expression.
But wait! If newlines don't count as "next statement", then how the hell do I tell Haskell to perform several actions in order? Like, for example, first do putStrLn, and then do countdown?
Well, this is where monads come in. Monads (of which IO is a prime example) were specifically brought into Haskell for this very reason: to express order of things. And the primary operation for that is "bind", which in Haskell exists in the form of an operator >>=. This operator takes a monadic value (such as IO Int or IO ()) on the left, and takes a function that returns a monadic value (such as Int -> IO String) on the right, and "glues" them together. The result is a new monadic action, which consists of the two input actions executed one after the other.
Applying this to your example with putStrLn and countdown, it would look like this:
putStrLn (show x) >>= (\y -> countdown (x-1))
^ ^ ^ ^
+---------------+ +---------------------+
\ \
first monadic value a function that takes the result of the
first action as parameter and returns
the second action
But this is a bit inconvenient. Sure, you can glue together two actions, maybe even three. But after a while this becomes very messy. (at first I had an example here, but then decided to do without; just trust me: it does get messy)
So to relieve the mess, the language now offers syntactic sugar in the form of the do notation. Inside the do notation, newline does, in fact, mean "next statement", and these consecutive "statements" get desugared into a sequence of calls to the >>= operator, giving them the semantics of "executing in order". Something like this:
do
y <- f x
z <- h y ====> f x >>= (\y -> h y >>= (\z -> g x y z))
g x y z
So to the naked eye the do notation does look roughly equivalent to multiple-line program in Python, Ruby, or JavaScript. But underneath it all, it's still a pure functional program, where everything is an expression, and the order of (non-pure, effectful) operations is explicitly controlled.
So, to summarize: you need to use do in your program to express the order - first putStrLn, and then countdown:
countdown :: Int -> IO ()
countdown x = if x <= 0
then putStrLn "The End."
else do
putStrLn (show (x))
countdown (x-1)
But you don't need to use do when there is just one operation, so there is no order to speak of.
And if you don't want to use do for whatever reason, you can desugar it manually into the equivalent >>= call:
countdown :: Int -> IO ()
countdown x = if x <= 0
then putStrLn "The End."
else putStrLn (show (x)) >>= \_ -> countdown (x-1)
Can anyone tell me what is the problem with this Haskell program
import Control.Monad
import Data.Char
main = do
contents <- getContents
putStrLn $ contents
putStr $ "shortLinesOnly version is " ++ (shortLinesOnly contents)
putStr $ "printOnlyLessChars version is " ++ (printOnlyLessChars contents)
shortLinesOnly :: String -> String
shortLinesOnly input =
let allLines = lines input
shortLines = filter (\line -> length line < 10) allLines
result = unlines shortLines
in result
--------------------the other way of doing this is -----------------
printOnlyLessChars contents = unlines $ filter (\a -> length a < 10) $ lines $ contents
The program works fine, but it fails when I try to print the contents (line 5). Why is it having problems printing the string via putStrLn
The error message I get is
* Couldn't match expected type `(String -> IO ())
-> t0 -> IO String'
with actual type `IO String'
* The function `getContents' is applied to one argument,
but its type `IO String' has none
In the expression: getContents putStrLn
Thanks,
This is the line that you need to focus on:
In the expression: getContents putStrLn
This is haskell showing you how it views your code, but your code doesn't look like that. This is almost always an indentation error. Check that you don't have an extra space or a tab where it doesn't belong.
As a suggestion when reading haskell type error messages there are three places to look, and you should scan all of them before fixating on a single one:
The type signature information -- do your types really match?
The expression information -- does the expression the compiler sees match your expectations, or do you need to add $ or parens
Is there a typo or indentation problem.
I frequently feel my brain starting to overheat as I try to read through a really messy Couldn't match expected type so before I get too upset over trying to read that part of the error message I carefully check the In the expression: part to make sure that there is an easy to fix issue with how I entered the code.
I just start learning Template Haskell, and stuck on simple problem with splicing.
In one module I've implemented function tupleN which replies N-th element of the tuple:
tupleN :: Lift a => a -> Int -> Q Exp
tupleN a n = do
(TupE as) <- lift a
return $ as !! n
In the Main module I have:
main :: IO ()
main = do
let tup = (1::Int,'a',"hello")
putStrLn $ show $(tupleN $tup 1)
This seems to be working, but it wouldn't. Compiler prints error:
GHC stage restriction: `tup'
is used in a top-level splice or annotation,
and must be imported, not defined locally
In the expression: tup
In the first argument of `tupleN', namely `$tup'
In the expression: tupleN ($tup) 1
If I put tuple description right into spliced expression, code become working:
main :: IO ()
main = do
putStrLn $ show $(tupleN (1::Int,'a',"hello") 1)
What I missing with the first variant?
You've tried to use tup as a splice, but tup is just an ordinary value. You don't want to prefix it with a $.
Moreover, as the compile error states, since Template Haskell runs during the compilation process, GHC really needs to know what it's doing before it has finished compiling the current module. That means your splice expression can't depend on tup, because that's still being compiled. Inside splices, you can only use literals, imported values, and the special 'name and ''TypeName forms (which you can think of as a sort of literal, I suppose). You can get at some of the information from this compilation by using e.g. reify, but even that can only give you data that's available at compile time – if you want a function you can pass user input, or data constructed from user input, to, that's just impossible.
In short, you can't do exactly what you want to do using Template Haskell. You could, however, define a splice that expands to a function to get the ith element of a tuple of size sz:
import Control.Monad (unless)
import Language.Haskell.TH
tupleN :: Int -> Int -> Q Exp
tupleN sz i = do
unless (i < sz) . reportError $ "tupleN: index " ++ show i
++ " out of bounds for " ++ show sz ++ "-tuple"
lamE
[tupP (replicate i wildP
++ [varP (mkName "x")]
++ replicate (sz - i - 1) wildP)]
(varE (mkName "x"))
I have a hard time grasping this. When writing in do notation, how are the following two lines different?
1. let x = expression
2. x <- expression
I can't see it. Sometimes one works, some times the other. But rarely both. "Learn you a haskell" says that <- binds the right side to the symbol on the left. But how is that different from simply defining x with let?
The <- statement will extract the value from a monad, and the let statement will not.
import Data.Typeable
readInt :: String -> IO Int
readInt s = do
putStrLn $ "Enter value for " ++ s ++ ": "
readLn
main = do
x <- readInt "x"
let y = readInt "y"
putStrLn $ "x :: " ++ show (typeOf x)
putStrLn $ "y :: " ++ show (typeOf y)
When run, the program will ask for the value of x, because the monadic action readInt "x" is executed by the <- statement. It will not ask for the value of y, because readInt "y" is evaluated but the resulting monadic action is not executed.
Enter value for x:
123
x :: Int
y :: IO Int
Since x :: Int, you can do normal Int things with it.
putStrLn $ "x = " ++ show x
putStrLn $ "x * 2 = " ++ show (x * 2)
Since y :: IO Int, you can't pretend that it's a regular Int.
putStrLn $ "y = " ++ show y -- ERROR
putStrLn $ "y * 2 = " ++ show (y * 2) -- ERROR
In a let binding, the expression can have any type, and all you're doing is giving it a name (or pattern matching on its internal structure).
In the <- version, the expression must have type m a, where m is whatever monad the do block is in. So in the IO monad, for instance, bindings of this form must have some value of type IO a on the right-hand side. The a part (inside the monadic value) is what is bound to the pattern on the left-hand side. This lets you extract the "contents" of the monad within the limited scope of the do block.
The do notation is, as you may have read, just syntactic sugar over the monadic binding operators (>>= and >>). x <- expression de-sugars to expression >>= \x -> and expression (by itself, without the <-) de-sugars to expression >>. This just gives a more convenient syntax for defining long chains of monadic computations, which otherwise tend to build up a rather impressive mass of nested lambdas.
let bindings don't de-sugar at all, really. The only difference between let in a do block and let outside of a do block is that the do version doesn't require the in keyword to follow it; the names it binds are implicitly in scope for the rest of the do block.
In the let form, the expression is a non-monadic value, while the right side of a <- is a monadic expression. For example, you can only have an I/O operation (of type IO t) in the second kind of binding. In detail, the two forms can be roughly translated as (where ==> shows the translation):
do {let x = expression; rest} ==> let x = expression in do {rest}
and
do {x <- operation; rest} ==> operation >>= (\ x -> do {rest})
let just assigns a name to, or pattern matches on arbitrary values.
For <-, let us first step away from the (not really) mysterious IO monad, but consider monads that have a notion of a "container", like a list or Maybe. Then <- does not more than "unpacking" the elements of that container. The opposite operation of "putting it back" is return. Consider this code:
add m1 m2 = do
v1 <- m1
v2 <- m2
return (v1 + v2)
It "unpacks" the elements of two containers, add the values together, and wraps it again in the same monad. It works with lists, taking all possible combinations of elements:
main = print $ add [1, 2, 3] [40, 50]
--[41,51,42,52,43,53]
In fact in case of lists you could write as well add m1 m2 = [v1 + v2 | v1 <- m1, v2 <- m2]. But our version works with Maybes, too:
main = print $ add (Just 3) (Just 12)
--Just 15
main = print $ add (Just 3) Nothing
--Nothing
Now IO isn't that different at all. It's a container for a single value, but it's a "dangerous" impure value like a virus, that we must not touch directly. The do-Block is here our glass containment, and the <- are the built-in "gloves" to manipulate the things inside. With the return we deliver the full, intact container (and not just the dangerous content), when we are ready. By the way, the add function works with IO values (that we got from a file or the command line or a random generator...) as well.
Haskell reconciles side-effectful imperative programming with pure functional programming by representing imperative actions with types of form IO a: the type of an imperative action that produces a result of type a.
One of the consequences of this is that binding a variable to the value of an expression and binding it to the result of executing an action are two different things:
x <- action -- execute action and bind x to the result; may cause effect
let x = expression -- bind x to the value of the expression; no side effects
So getLine :: IO String is an action, which means it must be used like this:
do line <- getLine -- side effect: read from stdin
-- ...do stuff with line
Whereas line1 ++ line2 :: String is a pure expression, and must be used with let:
do line1 <- getLine -- executes an action
line2 <- getLine -- executes an action
let joined = line1 ++ line2 -- pure calculation; no action is executed
return joined
Here is a simple example showing you the difference.
Consider the two following simple expressions:
letExpression = 2
bindExpression = Just 2
The information you are trying to retrieve is the number 2.
Here is how you do it:
let x = letExpression
x <- bindExpression
let directly puts the value 2 in x.
<- extracts the value 2 from the Just and puts it in x.
You can see with that example, why these two notations are not interchangeable:
let x = bindExpression would directly put the value Just 2 in x.
x <- letExpression would not have anything to extract and put in x.
I am a total Haskell noob and I was hoping someone could help me with this because I've been at this for hours and I just know that I'm doing something ridiculously stupid.
The program is supposed to scan a dictionary file to determine all valid word sequences for a collection of sentences with spaces removed.
Ex. "insidewaysoften" could be broken down to "in side ways often", "inside way soften", etc.
I wrote my prototype in python and it works just fine (as does my Java implementation), but the course requires a Haskell implementation and I cannot get it to work. Apologies in advance for the crimes I have committed against the language and GHC with the following code:
import System.Environment
main = do
[dictFilename,sentFilename] <- getArgs
dictFile <- readFile dictFilename
sentFile <- readFile sentFilename
mapM (\sentence -> solve "" "" sentence (words dictFile)) (words sentFile)
solve prefix header [] dict =
if (header `elem` dict)
then return prefix ++ header
else return ""
solve prefix header sent dict = do
let more = solve prefix (header ++ (take 1 sent)) (drop 1 sent) dict
if (header `elem` dict)
then return (solve (prefix ++ header ++ " ") "" sent dict) ++ more
else return more
The first thing when investigating type errors is to write down the type signatures of functions you know.
Here, solve may have type
solve :: String -> String -> String -> [String] -> String
or
solve :: String -> String -> String -> [String] -> IO String
Depending on whether it should have any side-effects while computing the value. Seeing you using mapM and return all over the place, I guess the IO version may have been intended.
Now, if you write down the signature, you start getting much more meaningful error messages. For example, instead of this:
tmp.hs:19:16:
Couldn't match expected type `Char' with actual type `[Char]'
Expected type: [Char]
Actual type: [[Char]]
In the return type of a call of `solve'
In the first argument of `return', namely
`(solve (prefix ++ header ++ " ") "" sent dict)'
, which does not make much sense, you get this:
tmp.hs:14:8:
Couldn't match expected type `IO String' with actual type `[a0]'
In the expression: return prefix ++ header
In the expression:
if (header `elem` dict) then return prefix ++ header else return ""
In an equation for `solve':
solve prefix header [] dict
= if (header `elem` dict) then
return prefix ++ header
else
return ""
,which shows exactly where the problem is. Function application has the highest priority in Haskell, so return prefix ++ header is equivalent to (return prefix) ++ header, which is definitely not what you meant.
By the way, if I remove IO from the return type, remove all the returns and change the invocation by adding putStrLn, the code compiles and works! The only problem is that it concatenates all the possible sentences together into a single string without any delimiting.