This code does not compile in GHC 7.0.3:
import System.IO
main = do
z <- readLn
print z
My intention is to read one line from stdin and store it in z, to do more advanced stuff with it later on. Error message looks like:
test.hs:5:9:
Ambiguous type variable `a0' in the constraints:
(Show a0) arising from a use of `print' at test.hs:5:9-13
(Read a0) arising from a use of `readLn' at test.hs:4:14-19
Probable fix: add a type signature that fixes these type variable(s)
In a stmt of a 'do' expression: print z
In the expression:
do { z <- readLn;
print z;
return () }
In an equation for `main':
main
= do { z <- readLn;
print z;
return () }
Obviously there is something fundamental I haven't understood yet; please explain to me why it doesn't work and how to fix it.
EDIT1: I fixed the compile error by changing print z to putStrLn z, so GHC understands that I want to read a string. But when I run the program, I get a runtime error which I can't understand:
$ ./test
hello!
test: user error (Prelude.readIO: no parse)
$
I just typed "hello!" and then enter. Note that I'm running x86_64 GHC on OS X, which is considered unstable.
EDIT2: I changed readLn to getLine and it magically works for no reason. I would like to know why, but I'm happy it works.
Final code:
import System.IO
main = do
z <- getLine
print z
readLn as the type: Read a => IO a. It reads a line from the user, and then parses the string into type a. What is type a? It is whatever you want (as long as it is an instance of Read). For example:
readAInt :: IO Int
readAInt = readLn
readABool :: IO Bool
readABool = readLn
print has the type Show a => a -> IO (). It takes a type that is an instance of Show, and prints it out. For example, to print True, you can use print True. To print the Int 42, you can use print 42.
In your example, you are using print and readLn together. This doesn't work, as haskell can't figure out what type readLn should return. print can take any type that is showable, so it doesn't restrict to one what type would be returned. This makes the return type of readLn ambiguous as haskell can't figure out the type. This is what the error message is saying.
What you probably what it to store just the string being entered by the user, rather than reading it into your own type. You can do this with getLine, which has the type getLine :: IO String. Similarily you can use putStrLn instead of print to just print a String. putStrLn has the type String -> IO ().
This is what you changed your code to, right?
import System.IO
main = do
z <- readLn
putStrLn z
putStrLn writes a String to stdout, so z is a String. Therefore readLn will read a String from stdin.
BUT... readLn expects to read a Haskell-formatted value from stdin. i.e. instead of expecting you to type something like This is a string, it anticipates it in quote marks: "This is a string".
To fix, replace readLn with getLine, which reads in literal text, not a Haskell-formatted string.
import System.IO
main = do
z <- getLine
putStrLn z
readLn reads back a type that you specify, and so can't be used in this way: it needs to be used in a function that specifies its type. getLine, on the other hand, always returns a String, so it does what you want.
It's worth noting that you might want to use putStrLn instead of print as well; print will add quotation marks.
Thus do { z <- getLine; putStrLn z; } in GHCi should do what you want.
Related
I want to read a string from keyboard but i don't know why isn't working, I tried a lot of methods, but nothing worked! Can someone help me or give me an idea?
type Polinom = [Int]
scriePolinom :: Polinom -> String
....
main = do
a<-getLine
--let a=[2,-5,1]
scriePolinom a
Parse the line into the corresponding data:
import Data.List
parseIntList :: String -> [Int]
parseIntList s = [read x :: Int | x <- words s]
type Polinom = [Int]
scriePolinom :: Polinom -> String
....
main = do
a <- getLine
let intlist = parseIntList a
putStrLn $ scriePolinom intlist
GHCi, version 7.10.2: http://www.haskell.org/ghc/ :? for help
Prelude> :type getLine -- you can also write :t getLine
getLine :: IO String
This tells you that getLine always gives you (after doing some kind of impure I/O operations, in this case waiting for the user to enter some stuff on the keyboard, until pressing enter) a value of type String. Which makes sense: a string, also called...
Prelude> :info String -- you can also write :i String
type String = [Char] -- Defined in ‘GHC.Base’
...list of characters. These are just the exact characters/keys the user typed in. In general, these characters may not properly describe a Polinom – what, for example, if the user enters 34958oiyq4ulbwre?
What you need to do is trying to parse the input string to a more meaningfully-typed value, like Polinom. How to do that depends on what form you actually expect the input to be. If the user should use normal Haskell syntax for the coefficients, e.g. [2, -5, 1], you can use the standard read parser:
Prelude> scriePolinom (read "[2, -5, 1]")
"[2,-5,1]"
Or if, as Daniel Sanchez assumes, you expect just a sequence of space-separated numbers in decimal notation, you can first split up these numbers as words, then read each one individually:
Prelude> scriePolinom . map read $ words "2 -5 1"
"[2,-5,1]"
To use this in an executable program, you can use the ready-build combination of getLine and read:
main :: IO ()
main = do
a <- readLn
putStrLn $ scriePolinom a
Note that read/readLn are not robust with respect to malformed input (they're not total functions) – this will just crash the program unless you wrap it in explicit exception handling. For serious applications I recommend using a full-featured parsing library, such as megaparsec.
Haskell, 37 bytes
f l=[b|(a,b)<-zip[x<'b'|x<-'a':l]l,a]
Try it online!
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.
How do I create a program that reads a line from a file, parse it to an int and print it(ignoring exceptions of course). Is there anything like "read" but for IO String?
I've got this so far but I couldn't get around the IO types:
readFromFile = do
inputFile <- openFile "catalogue.txt" ReadMode
isbn <- read( hGetLine inputFile)
hClose inputFile
You can specify the type explicitly, change the read line to
isbn <- fmap read (hGetLine inputFile) :: IO Int
As hGetLine inputFile is of type IO String, you should use fmap to get "inside" to read as an Int.
You can use the readFile function to convert your file to a string.
main = do
contents <- readFile "theFile"
let value = read $ head $ lines contents::Int
print value
You should add better error detection, or this program will fail if there isn't a first line, or if the value is malformed, but this is the basic flow....
First, observe that reading stuff and then immediately printing it can result in mysterious errors:
GHCi, version 8.0.0.20160421: http://www.haskell.org/ghc/ :? for help
Prelude λ read "123"
*** Exception: Prelude.read: no parse
The reason is that you don't specify what type you want to read. You can counter this by using type annotations:
Prelude λ read "123" :: Integer
123
but it is sometimes easier to introduce a little helper function:
Prelude λ let readInteger = read :: String -> Integer
Prelude λ readInteger "123"
123
Now to the main problem. read( hGetLine inputFile) doesn't work because hGetLine inputFile returns and IO String and read needs a String. This can be solved in two steps:
line <- hGetLine inputFile
let isbn = readInteger line
Note two different constructs <- and let .. =, they do different things. Can you figure out exactly what?
As shown in another answer, you can do it in a less verbose manner:
isbn <- fmap readInteger (hGetLine inputFile)
which is great if you do a simple thing like read. But it is often desirable to explicitly name intermediate results. You can use <- and let .. = constructs in such cases.
I'm trying to get from my console a string or just a char and store into a variable.
I tried to use:
> let x = getChar
> x
> c -- for getting a char.
But nothing is stored (same for getLine) how can I do?
The type of getChar is IO Char. It is not a function that returns a Char; it is an IO action that, when executed, returns a Char. (While subtle, this distinction is crucial to understanding how Haskell performs IO with pure functions.)
The line
let x = getChar
just binds the name x to the same IO action (which you can see by subsequently typing :t x in GHCi). Typing x then executes that action; GHCI waits for you to type a character, then it immediately returns that character.
To use getChar in a program, you need to use it within an IO monad, with something like
main = do ch <- getChar
print ch
or
main = getChar >>= print
Here is a sample
main = do
x <- getLine
putStrLn $ "Here is the string you typed in: " ++ x
Reading from console, maybe is not very useful. However you should use <- construct.
For example (without " is good too) :
>myString <- getLine
>"Hello world"
or
>myChar <- getChar
>c
For more I suggest to read here
You need to bind it to a variable using <-, the result of an action is being bound:
*Main> variable <- getLine
hello
*Main> putStrLn variable
hello
*Main> anotherChar <- getChar
a*Main>
*Main> putChar anotherChar
a*Main>
Function getLine has type IO String and getChar has type IO Char.
I'm rather new to Haskell, and I'm currently using LearnYouAHaskell.
I am trying to take a string separated by white space, and break it into a list of smaller word strings.
My current program:
main = do
putStrLn "Insert a string to convert: "
-- Input string
line <- getLine
words line;
But in this case, it tells me I'm having an IO error.
TO my understanding, getLine is an action, and so since this is impure, I have to bind it to "line". Line is an accurate representation of getLine, which is an IO String.
However, shouldn't line be a string?
When I try to use words on line, it tells me
"Couldn't match expected type "IO a0" with actual type [String]
As if line isn't a string.
Furthermore, can I use :t line in the program itself when I make it to see if it's actual of the right type or not?
I apologize for the novice question, but I'm a bit stuck.
EDIT:
I did something similar in GHCI, and it tells me that my type is in fact a normal string.. I don't get it.
Prelude> line <- getLine
"Hello fellows"
Prelude> :t line
line :: String
Prelude> words line
["Hello","fellows"]
Why doesn't that work?
In haskell if you want to return a value, you have to say so:
main = do
putStrLn "Insert a string to convert: "
-- Input string
line <- getLine
return (words line)
words line isn't an IO action, it's a list of strings, so it can't be a statement in a do block.
return :: Monad m => a -> m a and in this case we can specialise it to the type a -> IO a and then to [String] -> IO [String]. Each of the statements in your do block must be IO statements.
Taking it further:
If you want to compile your program, you should have main :: IO(), which means you shouldn't return your list.
If, for example, you wanted to process those strings into a single string then output that, you could do
process :: [String] -> String
process xss = "I don't know, some answer"
main = do
putStrLn "Insert a string to convert: "
-- Input string
line <- getLine
putStrLn (process (words line))
although I'd personally write that last line as putStrLn $ process.words $ line.
Your interaction in GHCi
Prelude> line <- getLine
"Hello fellows"
Prelude> :t line
line :: String
Prelude> words line
["Hello","fellows"]
is using the fact that GHCi isn't actually just running in the IO monad. In GHCi, if your input is a valid line in a do block, it'll get run, but if it's pure code it'll get evaluated and printed. (An interactive interpreter like this is often called a REPL for Read-Eval-Print-Loop.)
Well, the question is what do you want to do with words line?
Having words line as a line inside a do block is doing nothing, but to get it to work you have to use return to wrap it up in the IO monad:
main = do
putStrLn "Insert a string to convert: "
-- Input string
line <- getLine
return (words line);
Anyway, perhaps you want to print it instead?
main = do
putStrLn "Insert a string to convert: "
-- Input string
line <- getLine
print (words line);