The only "user input" functions I know of in the Prelude return Strings - but often (I'd say more frequently) we want to read numbers or other types.
Is there a function of type :: IO a or similar, for reading a value of arbitrary type? I've searched hoogle for such a function, but either due to it not existing or due to the large number of other functions of similar type, I've not found anything.
It seems useful and simple enough that there must be a built-in. The closest I've come is this:
-- Eg.
get :: Read a => IO a
get = (liftM read) getLine
main = do
x <- get
print $ x + 5
There's readLn:
readLn :: Read a => IO a
Worth noting that readLn calls readIO in order to raise an IO exception instead of undefined.
Prelude> x <- (fmap read getLine) :: IO Integer
asdf
Prelude> x
*** Exception: Prelude.read: no parse
Prelude> x <- (readIO =<< getLine) :: IO Integer
asdf
*** Exception: user error (Prelude.readIO: no parse)
Related
This question already has an answer here:
How to use variable from do block assignment line in a where clause?
(1 answer)
Closed 2 years ago.
I was making a program with Haskell and it's IO, when I came across an error I don't understand. When I use a where statement after a do block it does not do the same thing as without the do block.
The program that works is:
import Control.Monad
prog :: IO()
prog = do m <- getLine
n <- getLine
p <- getLine
replicateM_ (read m :: Int) (putStrLn n)
replicateM_ (read m :: Int) (putStrLn p)
But when I replace the read m :: Int with a where statement like this:
import Control.Monad
prog1 :: IO()
prog1 = do m <- getLine
n <- getLine
p <- getLine
replicateM_ (a) (putStrLn n)
replicateM_ (a) (putStrLn p)
where
a = read m :: Int
I get the error:
Template.hs:23:21: error: Variable not in scope: m :: String
|
23 | a = read m :: Int
| ^
I have looked what the problem could be, and I think it has to do with the type of m, which is IO String. I know you have to stay in the IO type (once you are in it) to be able to work with the string. But I don't understand why the 'where' would "break out" of this IO type. To my understanding the two examples I gave are functional the same. First I thought that the error wouldn't be fixed by writing the program without the where, because the function read is from the type read :: Read a => String -> a and my input in the first program is also IO String. So why didn't my first program give me an error? Could someone explain what I understand wrong and how I can fix my program so I only have to execute read m :: Int once? Just some tips of how to use a where statement under a do block would also help.
The original program I got the problem in is longer and not all relevant so I used this minimal working example to explain the essence of my question. In my original program I have multiple statements after where, so I don't want to substitute it all like I did in this example.
The bindings in the do block are opaque to the where statement after it, so you can't reference anything defined in the do block inside the where statement. You don't need to either, since you can use let directly inside do:
prog1 = do m <- getLine
n <- getLine
p <- getLine
-- alternatively: [m, n, p] <- replicateM 3 getLine
-- use a let statement
let a = read m :: Int
replicateM_ a (putStrLn n)
replicateM_ a (putStrLn p)
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!
I'm fairly new to Haskell and have been trying to find a way to pass multiple IO-tainted values to a function to deal with a C library. Most people seem to use the <- operator inside a do block, like this:
g x y = x ++ y
interactiveConcat1 = do {x <- getLine;
y <- getLine;
putStrLn (g x y);
return ()}
This makes me feel like I'm doing C, except emacs can't auto-indent. I tried to write this in a more Lispy style:
interactiveConcat2 = getLine >>= (\x ->
getLine >>= (\y ->
putStrLn (g x y) >>
return () ))
That looks like a mess, and has a string of closed parentheses you have to count at the end (except again, emacs can reliably assist with this task in Lisp, but not in Haskell). Yet another way is to say
import Control.Applicative
interactiveConcat3 = return g <*> getLine <*> getLine >>= putStrLn
which looks pretty neat but isn't part of the base language.
Is there any less laborious notation for peeling values out of the IO taint boxes? Perhaps there is a cleaner way using a lift* or fmap? I hope it isn't too subjective to ask what is considered "idiomatic"?
Also, any tips for making emacs cooperate better than (Haskell Ind) mode would be greatly appreciated. Thanks!
John
Edit: I stumbled across https://wiki.haskell.org/Do_notation_considered_harmful and realized that the nested parentheses in the lambda chain I wrote is not necessary. However it seems the community (and ghc implementors) have embraced the Applicative-inspired style using , <*>, etc, which seems to make the code easier to read in spite of the headaches with figuring out operator precedence.
Note: This post is written in literate Haskell. You can save it as Main.lhs and try it in your GHCi.
A short remark first: you can get rid of the semicolons and the braces in do. Also, putStrLn has type IO (), so you don't need return ():
interactiveConcat1 = do
x <- getLine
y <- getLine
putStrLn $ g x y
We're going to work with IO, so importing Control.Applicative or Control.Monad will come in handy:
> module Main where
> import Control.Applicative
> -- Repeat your definition for completeness
> g :: [a] -> [a] -> [a]
> g = (++)
You're looking for something like this:
> interactiveConcat :: IO ()
> interactiveConcat = magic g getLine getLine >>= putStrLn
What type does magic need? It returns a IO String, takes a function that returns an String and takes usual Strings, and takes two IO Strings:
magic :: (String -> String -> String) -> IO String -> IO String -> IO String
We can probably generalize this type to
> magic :: (a -> b -> c) -> IO a -> IO b -> IO c
A quick hoogle search reveals that there are already two functions with almost that type: liftA2 from Control.Applicative and liftM2 from Control.Monad. They're defined for every Applicative and – in case of liftM2 – Monad. Since IO is an instance of both, you can choose either one:
> magic = liftA2
If you use GHC 7.10 or higher, you can also use <$> and <*> without import and write interactiveConcat as
interactiveConcat = g <$> getLine <*> getLine >>= putStrLn
For completeness, lets add a main so that we can easily check this functionality via runhaskell Main.lhs:
> main :: IO ()
> main = interactiveConcat
A simple check shows that it works as intended:
$ echo "Hello\nWorld" | runhaskell Main.lhs
HelloWorld
References
Applicative in the Typeclassopedia
The section "Some useful monadic functions" of LYAH's chapter "For a Few Monads More".
You can use liftA2 (or liftM2 from Control.Monad):
import Control.Applicative (liftA2)
liftA2 g getLine getLine >>= putStrLn
I have a file number.txt which contains a large number and I read it into an IO String like this:
readNumber = readFile "number.txt" >>= return
In another function I want to create a list of Ints, one Int for each digit…
Lets assume the content of number.txt is:
1234567890
Then I want my function to return [1,2,3,4,5,6,7,8,9,0].
I tried severall versions with map, mapM(_), liftM, and, and, and, but I got several error messages everytime, which I was able to reduce to
Couldn't match expected type `[m0 Char]'
with actual type `IO String'
The last version I have on disk is the following:
module Main where
import Control.Monad
import Data.Char (digitToInt)
main = intify >>= putStrLn . show
readNumber = readFile "number.txt" >>= return
intify = mapM (liftM digitToInt) readNumber
So, as far as I understand the error, I need some function that takes IO [a] and returns [IO a], but I was not able to find such thing with hoogle… Only the other way round seemes to exist
In addition to the other great answers here, it's nice to talk about how to read [IO Char] versus IO [Char]. In particular, you'd call [IO Char] "an (immediate) list of (deferred) IO actions which produce Chars" and IO [Char] "a (deferred) IO action producing a list of Chars".
The important part is the location of "deferred" above---the major difference between a type IO a and a type a is that the former is best thought of as a set of instructions to be executed at runtime which eventually produce an a... while the latter is just that very a.
This phase distinction is key to understanding how IO values work. It's also worth noting that it can be very fluid within a program---functions like fmap or (>>=) allow us to peek behind the phase distinction. As an example, consider the following function
foo :: IO Int -- <-- our final result is an `IO` action
foo = fmap f getChar where -- <-- up here getChar is an `IO Char`, not a real one
f :: Char -> Int
f = Data.Char.ord -- <-- inside here we have a "real" `Char`
Here we build a deferred action (foo) by modifying a deferred action (getChar) by using a function which views a world that only comes into existence after our deferred IO action has run.
So let's tie this knot and get back to the question at hand. Why can't you turn an IO [Char] into an [IO Char] (in any meaningful way)? Well, if you're looking at a piece of code which has access to IO [Char] then the first thing you're going to want to do is sneak inside of that IO action
floob = do chars <- (getChars :: IO [Char])
...
where in the part left as ... we have access to chars :: [Char] because we've "stepped into" the IO action getChars. This means that by this point we've must have already run whatever runtime actions are required to generate that list of characters. We've let the cat out of the monad and we can't get it back in (in any meaningful way) since we can't go back and "unread" each individual character.
(Note: I keep saying "in any meaningful way" because we absolutely can put cats back into monads using return, but this won't let us go back in time and have never let them out in the first place. That ship has sailed.)
So how do we get a type [IO Char]? Well, we have to know (without running any IO) what kind of IO operations we'd like to do. For instance, we could write the following
replicate 10 getChar :: [IO Char]
and immediately do something like
take 5 (replicate 10 getChar)
without ever running an IO action---our list structure is immediately available and not deferred until the runtime has a chance to get to it. But note that we must know exactly the structure of the IO actions we'd like to perform in order to create a type [IO Char]. That said, we could use yet another level of IO to peek at the real world in order to determine the parameters of our action
do len <- (figureOutLengthOfReadWithoutActuallyReading :: IO Int)
return $ replicate len getChar
and this fragment has type IO [IO Char]. To run it we have to step through IO twice, we have to let the runtime perform two IO actions, first to determine the length and then second to actually act on our list of IO Char actions.
sequence :: [IO a] -> IO [a]
The above function, sequence, is a common way to execute some structure containing a, well, sequence of IO actions. We can use that to do our two-phase read
twoPhase :: IO [Char]
twoPhase = do len <- (figureOutLengthOfReadWithoutActuallyReading :: IO Int)
putStrLn ("About to read " ++ show len ++ " characters")
sequence (replicate len getChar)
>>> twoPhase
Determining length of read
About to read 22 characters
let me write 22 charac"let me write 22 charac"
You got some things mixed up:
readNumber = readFile "number.txt" >>= return
the return is unecessary, just leave it out.
Here is a working version:
module Main where
import Data.Char (digitToInt)
main :: IO ()
main = intify >>= print
readNumber :: IO String
readNumber = readFile "number.txt"
intify :: IO [Int]
intify = fmap (map digitToInt) readNumber
Such a function can't exists, because you would be able to evaluate the length of the list without ever invoking any IO.
What is possible is this:
imbue' :: IO [a] -> IO [IO a]
imbue' = fmap $ map return
Which of course generalises to
imbue :: (Functor f, Monad m) => m (f a) -> m (f (m a))
imbue = liftM $ fmap return
You can then do, say,
quun :: IO [Char]
bar :: [IO Char] -> IO Y
main = do
actsList <- imbue quun
y <- bar actsLists
...
Only, the whole thing about using [IO Char] is pointless: it's completely equivalent to the much more straightforward way of working only with lists of "pure values", only using the IO monad "outside"; how to do that is shown in Markus's answer.
Do you really need many different helper functions? Because you may write just
main = do
file <- readFile "number.txt"
let digits = map digitToInt file
print digits
or, if you really need to separate them, try to minimize the amount of IO signatures:
readNumber = readFile "number.txt" --Will be IO String
intify = map digitToInt --Will be String -> [Int], not IO
main = readNumber >>= print . intify
I started with programming in Haskell about 4 month ago and now I came to the point where I have to deal with the IO system of Haskell.
I already did a lot of IO actions and haven't faced any problems I couldn't solve by myself, but this time I googled for almost two hours for no avail to get some information about the function readMaybe. So I have the following problem set to solve and I already tried a lot of different approaches to solve it but all the time I get the same failure message from my compiler:
No instance for (Read a0) arising from a use of `readMaybe'
The type variable `a0' is ambiguous
I understand what the compiler does want to tell me but I have no idea how to solve this problem. I already tried to add a class constraint, but without success.
So here is my very small and simple program that is just counting how many valid numbers the user has entered. The program is meant to terminate when the user enters an empty line.
This is just a auxiliary function I want to use for my project later on.
countNumbers :: IO Int
countNumbers = do
x <- count 0
return x where
count :: Int -> IO Int
count n = do
line <- getLine
case line of
"" -> do
return n
_ -> case readMaybe line of
Just _ -> do
x <- count (n+1)
return x
Nothing -> do
x <- count n
return x
Unfortunately I couldn't find out a lot of informations about the function readMaybe. The only thing I could find was in the Haskell library Text.Read:
readMaybe :: Read a => String -> Maybe aSource
Parse a string using the Read instance. Succeeds if there is exactly one valid result.
The very weird thing for me is that I have already written such a function that uses the readMaybe function and it worked perfectly ...
This program is just asking the user for a number and keeps asking as long as the user enters a valid number
getLineInt :: IO Int
getLineInt = do
putStrLn "Please enter your guess"
line <- getLine
case readMaybe line of
Just x -> do
return x
Nothing -> do
putStrLn "Invalid number entered"
x <- getLineInt
return x
So far as I can see there are no differences between the usage of the function readMaybe in the two programs and therefore it works in the one but not in the other :)
I would be really thankful for any hints from you!!
This has nothing to do with IO, so maybe you don't understand what the compiler is trying to tell you. There is a type variable a in readMaybe's signature; a has to have a Read instance, but other than that it can be anything. The compiler is telling you that it doesn't have any way to determine what you want a to be.
In getLineInt you don't have this problem, because you are returning the result of readMaybe and the type signature says it should be Int. In countNumbers, you're not using the result of readMaybe, so there's nothing that can be used to determine the correct type. You can fix this by adding an explicit type signature (I picked Int since you're apparently counting numbers):
_ -> case readMaybe line :: Maybe Int of
Finally a word about do notation: it's just syntactic sugar, you don't have to use it all the time. Instead of do return x you can simply write return x, and instead of
x <- getLineInt
return x
you can simply do
getLineInt
That makes things more readable:
getLineInt :: IO Int
getLineInt = do
putStrLn "Please enter your guess"
line <- getLine
case readMaybe line of
Just x -> return x
Nothing -> putStrLn "Invalid number entered" >> getLineInt
Why does this happen?
In your second function, it is clear that readMaybe line is used as String -> Maybe Int, since type inference notices that you use return x and therefore x must be an Int.
In your first function, you don't use the Maybe's value at all, you just want to check whether the read succeeded. However, since you didn't specify the type (neither explicit nor implicit with type inference), the type variable is ambiguous:
_ -> case readMaybe line of
There's an easy fix: annotate the type:
_ -> case readMaybe line :: Maybe Int of
By the way, this is exactly the same behaviour you encounter when you use read in ghci without any type context:
> read "1234"
<interactive>:10:1:
No instance for (Read a0) arising from a use of `read'
The type variable `a0' is ambiguous
As soon as you make the type clear everything is fine:
> read "1234" :: Int
1234
Making things clear
Now that we've seen why the error happens, lets make this program much simpler. First of all, we're going to use a custom readMaybe:
readMaybeInt :: String -> Maybe Int
readMaybeInt = readMaybe
Now how does one count numbers? Numbers are those words, where readMaybeInt doesn't return Nothing:
countNumbers :: String -> Int
countNumbers = length . filter isJust . map readMaybeInt . words
How does one now calculate the numbers in the standard input? We simply take input until one line is completely empty, map countNumbers on all those lines and then sum:
lineNumberCount :: IO Int
lineNumberCount =
getContents >>= return . sum . map countNumbers . takeWhile (/= "") . lines
If you're not used to the bind methods, that's basically
lineNumberCount :: IO Int
lineNumberCount = do
input <- getContents
return . sum . map countNumbers . takeWhile (/= "") . lines $ input
All in all we get the following terse solution:
import Control.Monad (liftM)
import Data.Maybe (isJust)
import Text.Read (readMaybe)
readMaybeInt :: String -> Maybe Int
readMaybeInt = readMaybe
countNumbers :: String -> Int
countNumbers = length . filter isJust . map readMaybeInt . words
lineNumberCount :: IO Int
lineNumberCount =
getContents >>= return . sum . map countNumbers . takeWhile (/= "") . lines
Now there's only one function working in the IO monad, and all functions are basically applications of standard functions. Note that getContents will close the handle to the standard input. If you want to use you're better of using something like
input :: String -> IO [String]
input delim = do
ln <- getLine
if ln == delim then return []
else input delim >>= return . (ln:)
which will extract lines until a line matching delim has been found. Note that you need to change lineNumberCount in this case:
lineNumberCount :: IO Int
lineNumberCount =
input "" >>= return . sum . map countNumbers