Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
326 views
in Technique[技术] by (71.8m points)

haskell - Read a string input

I am trying to write instance of Read class to read an input as string as follow:

"1 3 -    
 - 2 3      
 - - 5" 

Convert it into [[Maybe Int]]

"-" will be translated into Nothing "3" will be Just 3

"('a',3) - ('b',7)
 ('c',5) ('e',0) -  
 ('d',9) - ('h',8)"

Convert it into [[Maybe (Char,Int)]]

"-" will be translated into Nothing "('a',3)" will be Just ('a',3)

I tried to write them by handling with List of Char, but it takes a lot of work. Do you have any suggestion? Sorry, I am quite new to Haskell, so I ask you that question. :(

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

If you got rid of the - entries, you could do this very quickly as

Prelude> (map (map read) . map words. lines $ "('a',3) ('b',4)
('c',5)")::[[(Char,Int)]]
[[('a',3),('b',4)],[('c',5)]]

Or define it as a function

genericReadLines :: Read a => String -> [[a]]
genericReadLines = map (map read) . map words. lines

Which you can use thus:

*Main> (genericReadLines "('a',3) ('b',4)
('c',5)")::[[(Char,Int)]]
[[('a',3),('b',4)],[('c',5)]]

but you may find it easier to do

readCharInts :: String -> [[(Char,Int)]]
readCharInts = genericReadLines

readInts :: String -> [[Int]]
readInts = genericReadLines

So you can just type

*Main> readInts "1 2 3
4 5 6
7 8 9"
[[1,2,3],[4,5,6],[7,8,9]]
*Main> readCharInts "('a',3) ('b',4)
('c',5)"
[[('a',3),('b',4)],[('c',5)]]

But what about keeping the -? You'll have to use a Maybe data type, to represent not having a value for certain points in your list; we can use - as shorthand for Nothing and a as shorthand for Just a.

read' :: Read a => String -> Maybe a
read' "-" = Nothing
read' xs = Just (read xs)

I should warn you that that code is fragile if your data could possibly be '-', but perhaps it can't.

genericMaybeReadLines :: Read a => String -> [[Maybe a]]
genericMaybeReadLines = map (map read') . map words. lines

Then we can have

readMaybeCharInts :: String -> [[Maybe (Char,Int)]]
readMaybeCharInts = genericMaybeReadLines

readMaybeInts :: String -> [[Maybe Int]]
readMaybeInts = genericMaybeReadLines

So now we can do

*Main> readMaybeCharInts "('a',3) ('b',4)
- ('c',5)"
[[Just ('a',3),Just ('b',4)],[Nothing,Just ('c',5)]]
*Main> readMaybeInts "2 3 -
4 - 2"
[[Just 2,Just 3,Nothing],[Just 4,Nothing,Just 2]]

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...