I am trying to make a guess the number game.
`
main :: IO()
checkGuess :: (Integral a) => a -> Bool
checkGuess b = if b == 9 then return True
main = do
print "Guess the number?"
guess <- getLine
checkGuess guess
but I get parse error on input '::' at the function checkGuess
There are several things that are wrong here:
you do not define the function directly after you wrote the signature of the function. You thus should first write the signature, and then write its binding, strictly speaking this is not an error as #chi says, but it is nevertheless strongly recommended;
In Haskell indentation matters: entering and leaving an indentation level says that you start or end a code block, for example for a where clause;
your checkGuess is supposed to return a Bool, but with return True, you make it a Monad m => m Bool;
in Haskell an if ... then ... else ... without an else does not exist. That is logical since a function should always return something;
getLine has as type IO String, so guess has type String, not Int, Integer, so you can not use guess directly to compare with a number; and
as #Krantz pointed out, the print here should probably be a putStrLn, since otherwise we print a string literal, not the string content.
In general it looks like you are writing an imperative program in a (pure) function language. A quick fix is the following:
checkGuess :: (Eq a, Num a) => a -> Bool
checkGuess = (9 ==)
main :: IO()
main = do
putStrLn "Guess the number?"
guess <- readLn :: IO Int
print (checkGuess guess)
Related
I am trying following code with try-catch block:
import System.Environment
import System.IO
import System.IO.Error
import Control.Exception
isBinary :: String -> Bool
isBinary ss = do
print "In isBinary fn" -- works if this line is removed.
let ans = any (\c -> ord c > 127) ss
ans
toTry :: String -> IO ()
toTry firline = do
print "In toTry fn."
let answer = isBinary firline
if not answer then do
print "Sent line not binary: "
else
print "Sent line binary"
handler :: IOError -> IO ()
handler e = putStrLn "Whoops, had some trouble!"
ss = "this is a test"
main = do
toTry ss `catch` handler
However, I am getting following error:
$ runghc trycatch3.hs
trycatch3.hs:9:9: error:
• Couldn't match expected type ‘Bool’ with actual type ‘IO Bool’
• In a stmt of a 'do' block: print "in isBinary fn"
In the expression:
do { print "in isBinary fn";
let ans = any (\ c -> ...) ss;
return ans }
In an equation for ‘isBinary’:
isBinary ss
= do { print "in isBinary fn";
let ans = ...;
return ans }
trycatch3.hs:10:30: error:
• Variable not in scope: ord :: Char -> Integer
• Perhaps you meant one of these:
‘or’ (imported from Prelude), ‘odd’ (imported from Prelude)
The error goes away and program works well if the print statement is removed from isBinary function.
Why can't I put print statement in this function?
The answer is, "because types". Specifically:
isBinary :: String -> Bool
isBinary ss = do
....
Since it's a do block, the return type of isBinary must match a monadic type Monad m => m t for some m and some t. Here, since print "" :: IO (), m is IO, so it should've been
isBinary :: String -> IO Bool
isBinary ss = do
and now
print "In isBinary fn" -- works
let ans = any (\c -> ord c > 127) ss -- also works
ans -- doesn't work
ans doesn't work because of types, again. Its type is Bool, but it must be IO Bool -- first, because this do block belongs to IO monad, on account of print; and second, because of the return type of the function as a whole.
Instead, use
return ans
and now it'll work, because return injects a value into the monadic context, and being the last do block value it becomes the value produced by the do block overall (if return val appears in the middle it just passes the val to the next step in the combined computation).
The function toTry will have to be augmented to use the new definition:
toTry :: String -> IO ()
toTry firline = do
print "In toTry fn."
-- let answer = isBinary firline -- incorrect, now!
answer <- isBinary firline -- isBinary ... :: IO Bool
if not answer then do -- answer :: Bool
print "Sent line not binary: "
else
print "Sent line binary"
m a on the right of <-, a on the left.
See this for a general description of do notation.
You might be confused by the same print line working in toTry, but not in isBinary. The difference stems from the declaration:
isBinary :: String -> Bool
This means that isBinary is a pure function (i.e. no side effects), taking a string and returning a boolean. In fact, you could simplify it to
isBinary ss = any (\c -> ord c > 127) ss
or even use the point-free style
isBinary = any (\c -> ord c > 127)
However, toTry is
toTry :: String -> IO ()
I.e. it takes a string and returns the IO monad which is impure (can have side effects, such as printing text to the console).
Haskell is a language that encourages using pure functions, and enforces it using the type system, by forcing the programmer to explicitly mark impure code.
Further reading:
What does "pure" mean in "pure functional language"?
Looking at your code, it seems your use of print in isBinary is not an integral part of what you want the function to do, but merely a debug print statement that will be removed later on. In that case, you do not want to change the type of isBinary to String -> IO Bool (for more on that, see Will Ness' answer), as you don't actually need IO except for debugging. Rather, the core libraries offer the Debug.Trace module, which caters to this kind of situation. With it, we can add your debug print statement like this:
isBinary :: String -> Bool
isBinary ss = trace "In isBinary fn" $ any (\c -> ord c > 127) ss
Then, once you are done debugging, you can remove the use of trace -- and it bears repeating you really should do that later on. Quoting the Debug.Trace documentation:
Functions for tracing and monitoring execution.
These can be useful for investigating bugs or performance problems. They should not be used in production code.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
Can I ask why I get this?
Couldn't match type Char' with[Char]'
Expected type: [String]
Actual type: [Char]
In the second argument of (:)', namelystart'
In the expression: (show gm : start)
main :: IO ()
main = do
c <- parseArguments <$> getArgs
input <- hGetContents stdin
either print (handleGM input) c
handleGM input Config{..} = do
handleGM <$> readFile tgrammer >>= either putStrLn (mapM_ putStrLn)
where
handleGM gm = do
gm' <- parseGM gm
case action of
Simulate -> printGrammer gm' input
printGrammer gm#TGrammer{..} input =
(show gm:start)
Data:
type TState = String
type TSymbol = Char
data TGrammer = TGrammer
{ neterminaly :: [TState]
, terminaly :: [TState]
, start :: [Char]
, rules :: [Rules]
}
deriving (Show)
data Rules = Rules
{ from :: TSymbol
, to :: String
}
deriving (Show)
There are quite a few things that are very weird about your code, so hopefully correcting them will help you solve your problem.
Type Signatures
You should always include type signatures on your top-level bindings, as well as any non-trivial where or let bindings. These are my best guesses as to what you intended the types to be:
handleGM :: String -> Config -> IO ()
printGrammer :: TGrammer -> String -> IO ()
Shadowed Binding
handleGM appears to be defined twice, once inside of itself in a where binding. This is really bad practice because it looks like you are trying to do a recursive call. You should consider renaming the internal function, or in this case, just writing it out in the do-notation, since its not recursive (and therefore doesn't need the where binding). In fact, you have misused <$>, which should only be used to map a pure function over an impure value. In this case, you are trying to use it to map an impure function of an impure value, which results in the confusing and not-what-you-want selection of Either String () as the type for the inside handleGM.
Operator overuse
It's best not to use <$> and >>= if your code isn't working, as it can hide what is actually happening, so write them out explicitly (do-notation) when you have problems like this.
Here is how I would revise handleGM so based on the above:
handleGM :: String -> Config -> IO ()
handleGM input Config{..} = do
a <- readFile tgrammer
b <- either putStrLn (mapM_ putStrLn) a
gm' <- parseGM b
case action of
Simulate -> printGrammer gm' input
[Char] doesn't match Char
This is because you used the cons operator (:) :: Char -> [Char] -> [Char], but the first argument you gave it was already a [Char] (namely, show gm). What you probably want is (++) :: [Char] -> [Char] -> [Char] which will put your two [Char] together into one longer [Char]. You probably also want to print to the terminal rather than just compute a [Char], which means you need to use a function like putStrLn :: String -> IO (). If these are accurate, here is what I would revise printGrammer to:
printGrammer :: TGrammer -> String -> IO ()
printGrammer gm#TGrammer{..} input = putStrLn (show gm ++ start)
Miscellaneous
You don't seem to actually do anything with input, so why bother passing it in at all?
You might benefit from turning on -Wall by passing it as an argument when you compile. It turns on all the compiler warning so it will tell you if you probably made a mistake.
You only have one case in your case. Why have the case there at all if it doesn't ever do anything different.
action seems to be pulled out of thin air; where does it come from?
I am trying to write to file a list of random Integers in a file. There seems to be a problem with writeFile here. When I use my function randomFile it says no instance for (Show (IO a0)). I see writeFile doesn't print anything to screen but IO(), so when I call the function randomFile 1 2 3 it says no Instance for Show (IO a0) but actually I just want to execute the function and not have to print anything but how can I avoid this problem. I might be making a lot of errors here. Any help.
import Control.Monad
import Control.Applicative
import System.Random
randNo mind maxd = randomRIO (mind,maxd)
randomFile mind maxd noe = do
let l=(replicate (fromInteger(noe ^ noe)) ( mind `randNo` maxd))
writeFile "RFile.txt" (show l)
I think you have a misunderstanding of what IO is. If you haven't done it, I strongly recommend going through the Input and Output section of Learn You a Haskell.
IO doesn't necessarily have anything to do with print. In Haskell every entry in memory that was made by your own code is considered "pure" while any entry that touches the rest of the computer lives in IO (with some exceptions you will learn about over time).
We model IO using something called a Monad. Which you will learn more about the longer you do Haskell. To understand this, let's look at an example of some code that does and doesn't use IO:
noIOused :: Int -> Int
noIOused x = x + 5
usesIO :: Int -> IO Int
usesIO x = print x >> return (x + 5)
usesIO2 :: Int -> IO Int
usesIO2 x = do
print x
return (x + 5)
The first function is "pure". The second and third functions have an IO "effect" that comes in the form of printing to the screen. usesIO and usesIO2 are just 2 different ways of doing the same thing (it's the same code but with different syntax). I'll use the second format, called do notation from here.
Here are some other ways you could have had IO effects:
add5WithFile :: Int -> IO Int
add5WithFile x = do
writeFile "someFile.txt" (show x)
return (x + 5)
Notice that in that function we didn't print anything, we wrote a file. But writing a file has a side effect and interacts with the rest of the system. So any value we return has to get wrapped in IO.
addRandom :: Int -> IO Int
addRandom x = do
y <- randomRIO (1,10)
return (x + y)
In addRandom we called randomRIO (1,10). But the problem is that randomRIO doesn't return an Int. It returns an IO Int. Why? Because in order to get true randomness we need to interact with the system in some way. To get around that, we have to temporarily strip away the IO. That's where this line comes in:
y <- randomRIO (1,10)
That <- arrow tells us that we want a y value outside of IO. For as long as we remain inside the do syntax that y value is going to be "pure". Now we can use it just like any other value.
So for example we couldn't do this:
let w = x + (randomRIO (1,10))
Because that would be trying to add Int to IO Int. And unfortunately our + function doesn't know how to do that. So first we have to "bind" the result of randomRIO to y before we can add it to x.
Now let's look at your code:
let l=(replicate (fromInteger(noe ^ noe)) ( mind `randNo` maxd))
writeFile "RFile.txt" (show l)
The type of l is actually IO a0. It's a0 because you haven't told the compiler what kind of number you want. So it doesn't know if you want a fraction, a double, a big integer or whatever.
So the first problem is to let the compiler know a little bit more about what kind of random number you want. We do this by adding a type annotation:
randNo :: Int -> Int -> IO Int
randNo mind maxd = randomRIO (mind,maxd)
Now both you and the compiler knows what kind of value randNo is.
Now we need to "bind" that value inside of the do notation to temporarily escape IO. You might think that would be simple, like this:
randomFile mind maxd noe = do
l <- replicate (fromInteger(noe ^ noe)) ( mind `randNo` maxd)
writeFile "RFile.txt" (show l)
Surely that will "bind" the IO Int to l right? Unfortunately not. The problem here is that replicate is a function of the form Int -> a -> [a]. That is, given a number and a type, it will give you a list of that type.
If you give replicate an IO Int it's going to make [IO Int]. That actually looks more like this: List (IO Int) except we use [] as syntactic sugar for lists. Unfortunately if we want to "bind" an IO value to something with <- it has to be the out-most type.
So what you need is a way to turn an [IO Int] into an IO [Int]. There are two ways to do that. If we put \[IO a\] -> IO \[a\] into Hoogle we get this:
sequence :: Monad m => [m a] -> m [a]
As I mentioned before, we generalise IO to something called a Monad. Which isn't really that big a deal, we could pretend that sequence has this signature: sequence :: [IO a] -> IO [a] and it would be the same thing just specialised to IO.
Now your function would be done like this:
randomFile mind maxd noe = do
l <- sequence (replicate (fromInteger(noe ^ noe)) ( mind `randNo` maxd))
writeFile "RFile.txt" (show l)
But a sequence followed by replicate is something people have to do all the time. So someone went and made a function called replicateM:
replicateM :: Monad m => Int -> m a -> m [a]
Now we can write your function like this:
randomFile mind maxd noe = do
l <- replicateM (fromInteger(noe ^ noe)) ( mind `randNo` maxd)
writeFile "RFile.txt" (show l)
And for some real Haskell magic, you can write all 3 lines of code in a single line, like this:
randomFile mind maxd noe = randomRIO >>= writeFile "RFile.txt" . replicateM (fromInteger(noe ^ noe))
If that looks like gibberish to you, then there's a lot you need to learn. Here is the suggested path:
If you haven't already, start from the beginning with Learn You a Haskell
Then learn about how You could have invented Monads
Then learn more about how to use randomness in Haskell
Finally see if you can complete the 20 intermediate Haskell exercises
I'm trying to do a function which returns true or false.
owlFile = ".+\\.owl"
testOwlFile src = src =~ owlFile :: Bool
And i need to use on my do block :
main = do
[src] <- getArgs
resTestOwlFile <- testOwlFile
if resTestOwlFile
then do ontology <- runX(readDocument [withValidate no,withRemoveWS yes ] src >>> getontology)
else print "error"
But i'm having an error which is Couldn't match excepted type IO BOOL with actual type Bool In the return type of a call of "testOwlFile"
What can i do for that ?
Please avoid, generally, to think about "converting". Sometimes you actually need to do that, but normally the type system gives you just the right type at the right spot if you use it correctly.
IO Bool is not a boolean value, but an action that, possibly together with side effects, will also yield a boolean value. So why would you "convert" a perfectly good pure value to such an action, one that doesn't actually do any of the stuff it's type is there for? That doesn't make much sense. The right thing to do, as already said, is to use the value directly; I'd just put it straight in the if condition:
main = do
[src] <- getArgs
if src =~ owlFile
then ...
else ...
That said, this conversion Bool -> IO Bool, however useless, is certainly possible. Indeed, for any monad1 m, that is one of the fundamental operations:
class Monad m where
return :: a -> m a
So you could in principle write
resTestOwlFile <- return testOwlFile
But don't. That is always equivalent to let resTestOwlFile = testOwlFile (guaranteed by the monad laws).
1
The weaker Applicative is actually sufficient.
The problem is that testOwlFile is of type Bool, but the <- notation expects an IO something.
If testOwlFile did have type IO Bool, then resTestOwlFile would have type Bool and your code would have built fine.
As #user2407038 pointed out in a comment, you can use let instead of <- when the thing you are defining has the same type as the expression you are defining it with:
let resTestOwlFile = testOwlFile
Or you could just use testOwlFile directly in the if statement on the next line.
Note that more generally the <- notation expects m something for any m that's an instance of the Monad class, but in this case m must be IO because you're defining the main function and because of other code in the do block like getArgs and print.
i wonder can a IO() function return tuple because i would like to get these out of this function as input for another function.
investinput :: IO()->([Char], Int)
investinput = do
putStrLn "Enter Username : "
username <- getLine
putStrLn "Enter Invest Amount : "
tempamount <- getLine
let amount = show tempamount
return (username, amount)
Please help.
Thanks.
IO in Haskell doesn't work like IO in the languages you're used to. All functions in Haskell must be pure: that is, if a function f is called with the argument x, there must be no difference between calling it once, twice, or a hundred times. Consider what this means for IO, though. Naïvely, getLine should have the type getLine :: String, or perhaps getLine :: () -> String. (() is the unit type, whose only value is (); it's sort of like a void type in a C-like language, but there is a single value of it.) But this would mean that every time you wrote getLine, it would have to return the same string, which is not what you want. This is the purpose of the IO type: to encapsulate actions. These actions are distinct from functions; they represent impure computation (though they themselves are pure). A value of type IO a represents an action which, when executed, returns a value of type a. Thus, getLine has type getLine :: IO String: every time the action is evaluated, a String is produced (by reading from the user). Similarly, putStr has type putStr :: String -> IO (); it is a function which takes a string and returns an action which, when run, returns no useful information… but, as a side effect, prints something to the screen.
You are attempting to write a function of type IO () -> ([Char], Int). This would be a function which took as input an action and returned a tuple, which is not what you want. You want an IO (String, Int)—an action which, when run, produces a tuple consisting of a string (which is a synonym for [Char]) and an integer. You're almost there with your current code, too! This is what you'll need instead:
investinput :: IO (String, Int)
investinput = do
putStrLn "Enter Username : "
username <- getLine
putStrLn "Enter Invest Amount : "
tempamount <- getLine
let amount = read tempamount
return (username, amount)
Notice that I've only made two changes (and removed a blank line). First, I've changed the type of the function, like I said above. Second, I changed show into read. The show function has the type Show a => a -> String: it is a function which takes anything which can be shown and produces a string representing it. You wanted read, which has the type Read a => String -> a: given a string, it parses it and returns some readable value.
The other thing you asked about is returning a tuple (String, Int) instead of an action IO (String, Int). There is no pure way to do this; in other words, there is no pure function IO a -> a. Why is this? Because IO a represents an impure action which depends on the real world. If we had such a function impossibleRunIO :: IO a -> a, then we would want it to be the case that impossibleRunIO getLine == impossibleRunIO getLine, since the function must be pure. But this is useless, as we would want impossibleRunIO to be able to actually interact with the real world! Thus, this pure function is impossible. Everything that enters IO can never leave. This is what return does: it is a function with, in this case1, the type return :: a -> IO a, which enables you to place pure values into IO. For any x, return x is an action which, when run, always produces x. This is why you have to end your do block with the return: username is a pure value you extracted from an action, and as such is only visible within the do block. You need to lift it into IO before the outside world can see it. The same is true of amount/tempamount.
And just for completeness's sake: there is some overarching theory behind this which ties it together. But it's not necessary at all for beginning Haskell programming. What I would recommend doing is structuring most of your code as pure functions which fold, spindle, and mutilate your data. Then construct a thin (as thin as possible) IO front layer which interacts with said functions. You'll be surprised how little IO you need!
1: It actually has a more general type, but that's not relevant for the moment.
Yeah, you're almost there but I think you want the signature:
investinput :: IO ([Char], Int)
... then from the calling function you can do something like:
main = do
(username, amount) <- investinput
....
I think you want to read tempamount rather than show though.
An IO function that produces a tuple would have type IO (a, b), in this case:
investinput :: IO ([Char], Int)
A signature of IO () -> ([Char], Int) would mean that the function takes a parameter of type IO () and produces a tuple from that, which is not what you want.
Generally there are no restrictions on the types an IO function (or a function in a different monad) can return, you can chose the types however you like.
The answer to your question about returning (String, Int) rather than IO (String, Int) is simple: you can't. Once you're in IO you're stuck there. That's part of what it means when people say that Haskell is a "pure" language.
What you want to do is similar to what you're already doing here with getLine. The type of getLine is IO String. When you write username <- getLine, you're in effect taking the String out of the IO String, but this is only possible because you're inside the do expression.
You can do exactly the same kind of thing with investinput as with getLine. Here's an example of how you could use investinput in your main function:
main = do
(name, amount) <- investinput
putStrLn $ name ++ " invested $" ++ show amount ++ "."
Since you mention liftM in a comment, here's a full working version that does the same thing using liftM and the reverse bind operator (=<<) instead of do notation:
import Control.Monad (liftM)
investinput :: IO (String, Int)
investinput = do
putStrLn "Enter Username : "
username <- getLine
putStrLn "Enter Invest Amount : "
amount <- liftM read getLine -- We can also use liftM to get rid of tempamount.
return (username, amount)
summary :: (String, Int) -> String
summary (name, amount) = name ++ " invested $" ++ show amount ++ "."
main = putStrLn =<< liftM summary investinput
This shows how you could use investinput with "another function which expects a tuple".