How to enter multiple values ​​on one line in haskell

For example, I want to write a program that will take 3 integers as input from the command line. The functions that I learned are readLnfor reading values ​​from the entire string. But readLnit seems to parse the entire string as a single value. How can I get three values ​​of one string with haskell?

+4
source share
3 answers

Read the line with getLine, divide it into wordsand readeach:

readInts :: IO [Int]
readInts = fmap (map read.words) getLine

it reads any number of messages:

ghci> readInts
1 2 3
[1,2,3]
ghci> readInts
1 2 3 4 5 6
[1,2,3,4,5,6]

You can limit three:

read3Ints :: IO [Int]
read3Ints = do
     ints <- readInts
     if length ints == 3 then return ints else do
         putStrLn ("sorry, could you give me exactly three integers, "
                  ++ "separated by spaces?")
         read3Ints

which is as follows:

ghci> read3Ints
1 2
sorry, could you give me exactly three integers, separated by spaces?
1 23 , 5, 6
sorry, could you give me exactly three integers, separated by spaces?
1,2,3
sorry, could you give me exactly three integers, separated by spaces?
1 3 6

Secrets fmap

fmapworks a bit like map, but you can use it more widely:

ghci> fmap (*10) [1,2,3,4]
[10,20,30,40]
ghci> fmap (*10) (Just 5)
Just 50
ghci> map (fmap (*10)) [Left 'b', Right 4, Left 'c', Right 7]
[Left 'b',Right 40,Left 'c',Right 70]
ghci> fmap words getLine
Hello there me hearties!
["Hello","there","me","hearties!"]

getInts fmap (map read.words), , map read, Int. , Int - - , .

+12

, reads. Read a => ReadS a, ReadS a String -> [(a, String)]. , , , , . , , . :

> reads "1 2 3" :: [(Int, String)]
[(1, " 2 3")]
> reads " 2 3" :: [(Int, String)]
[(2, " 3")]

, Int, , , . . (s -> [(a, s)]) -> s -> [a], :

chain :: (s -> [(a, s)]) -> s -> [a]
chain f s = case f s of
    [] -> []
    [(a, newS)] -> a : chain f newS
    xs -> map fst xs ++ chain f (last $ map snd xs)

> chain reads "1 2 3" :: [Int]
[1, 2, 3]
> chain reads "1 2 3 asdf" :: [Int]
[1, 2, 3]
> chain reads "asdf 1 2 3" :: [Int]
[]

read3Ints :: String -> [Int]
read3Ints = take 3 . chain reads
+2

:

    getInts::[Int]
    getInts = do s<-getLine
                 map read . words $ s
+1

Source: https://habr.com/ru/post/1527736/


All Articles