[Haskell-cafe] Newbie question about Read strings in a line of File

Cale Gibbard cgibbard at gmail.com
Tue Jul 26 14:39:48 EDT 2005

Here's how I wrote it:

----- beginning of file
import IO

-- turn a line of the text file into a pair consisting of
-- the message triple and the message string
-- slight bug: will contract multiple spaces in the message string
-- This could be rewritten to avoid this problem, but couldn't make as
much use of
-- existing prelude functions to do the work.
readMessage :: String -> ((Integer, Integer, Integer), String)
readMessage line = let (lang:typ:idx:msgWds) = words line
                       msg = unwords msgWds
                   in ((read lang, read typ, read idx),msg)

-- An IO action which gets a list of such pairs given a filename.
readMessagesFile filename = do hdl <- openFile filename ReadMode
                               cs <- hGetContents hdl
                               return $ map readMessage (lines cs)

-- An IO action which gets a lookup function for the message codes
given a filename.
getMessageLookup :: String -> IO ((Integer, Integer, Integer) -> Maybe String)
getMessageLookup filename = do msgs <- readMessagesFile filename
                               return (flip lookup msgs)
----- end of file

You can then test this in GHCi with something like
msgLookup <- getMessageLookup "messages.txt"
msgLookup (1,1,1)
which should result in:
Just "Error message 1"

The values are wrapped in the "Just" constructor, and typed in the
Maybe monad, since the lookup might fail, in which case the msgLookup
will return the value "Nothing". Also note that this is somewhat
inefficient for very large numbers of messages, (lookup will be linear
in the number of messages in the worst case.) To get better
performance, a Map (see Data.Map) could be constructed, and the
lookups done on that, resulting in logarithmic time performance. The
interface would remain the same.

Hope this helps,
 - Cale

On 26/07/05, Huong Nguyen <hiperfume at gmail.com> wrote:
> Hello everybody,
> Now I am writing a module to handles messages of a system. The
> messages are stored in a file. The content of each line of the file
> likes this:
>    1        001          001           Error message 1
>    1        001          002           Error message 2
>    1        002          001           Warning message 1
> in which: The first word is the language Code (e.g: 1 is English, 2 is
> French), the second is type of messages (e.g: 001 is error message,
> 002 is warning message,etc), the third is the index number of
> messages, and the last is the message. I need to read 3 first words of
> each line and assign them to 3 variables. After that, I need to show
> the error message based on the tuple of those 3 first variable, e.g:
> errMsg("1","001","001") = "Error message 1"
> At first, I tried to read only one first line of the file as follows:
> import Prelude
> import List
> import Char
> import IO
> main = do hdl <- openFile "message.txt" ReadMode
>                msgLine <-hGetLine hdl
> --stdMsg: cut space at the begining of the line.
>                let stdMsg = dropWhile(not.isSpace) msgLine
> -Assign langCode with the first word of the line.
>                let langCode = takeWhile(not.isSpace) stdMsg
> However, after that, I do not know how to read second element, third
> element of the line. And how to read continuous next line after first?
> Please help me. Thanks a lot.
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe

More information about the Haskell-Cafe mailing list