Reputation: 583
I've written following code:
module Test where
import Char
import IO
main = do
str <- readFile "no.txt"
putStrLn (show(english str))
string2list :: String -> [String]
string2list "" = []
string2list s = words s
english :: String -> Int
english s
| head (string2list s) == "one" = 1
| head (string2list s) == "two" = 2
| head (string2list s) == "three" = 3
| head (string2list s) == "four" = 4
| head (string2list s) == "five" = 5
| head (string2list s) == "six" = 6
| head (string2list s) == "seven" = 7
| head (string2list s) == "eight" = 8
| head (string2list s) == "nine" = 9
| otherwise = error "not match"
And in no.txt:
one
two
three
four
....
After compiled and run the code, I got the result:
1
But I expect to get:
1
2
3
4
...
What's wrong with the code? Any help? thx!
Upvotes: 2
Views: 1944
Reputation: 9891
Your problem is that english
only looks at the first word. Your file comes in as
"one\ntwo\nthree\nfour"
Then words
turns that into:
["one","two","three","four"]
Using head on that gives you:
"one"
And therefor 1
is printed.
Instaid we would like to use english on all the words. That is when map
comes in
handy, but in this case we are mapping an IO action onto the list, so we want to use mapM
. Furthermore we are not interested in the outcome of the IO action (we just want the action to happen) so we use mapM_
:
import Control.Monad
main = do
str <- readFile "no.txt"
mapM_ (print . english) (words str)
english "one" = 1
english "two" = 2
english "three" = 3
english "four" = 4
english "five" = 5
english "six" = 6
english "seven" = 7
english "eight" = 8
english "nine" = 9
Note that it is possible to write this using map
instaid of mapM
by first making ["one","two","three",...]
into ["1","2","3"]
, concating those strings, and then using putStrLn
, but the above way is both shorter and more idiomatic.
Upvotes: 2
Reputation: 10700
str
is not list of String (it's just a String like one\ntwo
) when read from readFile
. Do
main = do
str <- readFile "no.txt"
mapM_ (\x -> putStrLn (show(english x))) $ lines str
in your main
instead and convert str
to a list using lines
(see doc of lines ).
Upvotes: 6
Reputation: 92966
This is not an answer to your question but rather a stylistic advice. You can get rid of those wordy head (string2list s)
things by using pattern matching and by replacing string2list
with words
; both do exactly the same thing:
english s = case words s of
"one" :_ -> 1
"two" :_ -> 2
"three" :_ -> 3
"four" :_ -> 4
"five" :_ -> 5
"six" :_ -> 6
"seven" :_ -> 7
"eight" :_ -> 8
"nine" :_ -> 9
_ -> error "no match"
Upvotes: 5