Hi, I have some troubles with Haskell type system.
Situation:
- Following program is taking list of filenames on the cmdline
- For all filename it reads its content using the function readFile
- Content of each file is passed to inputParser (Parsec)
- Rest is not so important
- Main problem is in function read_modules
- First two statements of the 'do' expression are invalid in Haskell type system
- Problem is conflict between [String] x IO String x [Char] x ...
- Function 'parse' should take String but when it gets it, it wants IO String suddenly (on the same argument), otherwise it wants String
What do I want:
- Read each file content
- Pass that content to the 'parse' function as third argument
Here is the code.
module Main where
import System.IO
import System.Environment
import Text.ParserCombinators.Parsec
import InputParser
import Data
usage :: IO ()
usage = putStrLn "Usage: x file file file option"
parse_modules :: String -> [Char] -> Either ParseError [Module]
parse_modules filename input = parse inputParser filename input
read_modules :: [String] -> [Module]
read_modules [] = []::[Module]
read_modules (filename:rest) =
do
content <- readFile filename -- HERE is the problem
modules <- case parse_modules filename content of -- HERE is problem too
Left error -> do
putStr "parse error at "
print error
Right out -> out ++ (read_modules rest)
return modules
use :: [String] -> IO ()
use args =
do
init <- last args
filenames <- take (length args - 1) args
modules <- read_modules filenames
return ()
main :: IO ()
main = do args <- getArgs
if length args < 2
then usage
else use args
Here are the GHC output errors
ghc --make -o x.hs input-parser.hs data.hs
[3 of 3] Compiling Main ( x.hs, x.o )
x.hs:19:4:
Couldn't match expected type `IO String'
against inferred type `[String]'
In a stmt of a 'do' expression: content <- readFile filename
In the expression:
do content <- readFile filename
modules <- case parse_modules filename content of {
Left error -> do ...
Right out -> out ++ (read_modules rest) }
return modules
In the definition of `read_modules':
read_modules (filename : rest)
= do content <- readFile filename
modules <- case parse_modules filename content of {
Left error -> ...
Right out -> out ++ (read_modules rest) }
return modules
-- THIS ERROR is somewhat not important
x.hs:30:4:
Couldn't match expected type `[Char]'
against inferred type `IO Char'
Expected type: String
Inferred type: IO Char
In a stmt of a 'do' expression: init <- last args
In the expression:
do init <- last args
filenames <- take (length args - 1) args
modules <- read_modules filenames
return ()
make: *** [x] Error 1
What is the problem:
- I cannot understand what I should pass where. I kind of know what I want, but I don't get the syntax or the style.
- I am haskell greenie (not solving here)
- TYPES
What are the questions:
- How do I fix presented type issue? What should I put into 'parse' function? What 'readFile' gives to me? Are those two types compatible? Isn't there need for some type of conversion?
Relevant weblinks:
- http://book.realworldhaskell.org/read/using-parsec.html
- http://www.zvon.org/other/haskell/Outputprelude/readFile_f.html
- http://www.haskell.org/pipermail/haskell/2002-November/010748.html
Thank you all for your hints and comments.