openFile :: FilePath -> IOMode -> IO Handle
принимает FilePath
и IOMode
и дает IO Handle
.
Это означает, что
do
args <- getArgs
handle <- openFile args ReadMode
...
утверждает, что args
имеет тип FilePath
. Однако тип getArgs :: IO [String]
означает, что args
является [String]
, а не FilePath
. Это означает, что вы вызываете openFile
со списком строк, а не по пути к файлу.
Чтобы исправить это, во-первых, мы должны знать, что FilePath
это просто тип синоним String
, что означает, что мы должны взять элемент args
, а не весь список.
Вот пример, который делает это с помощью сопоставления с образцом:
do
[arg] <- getArgs
handle <- openFile arg ReadMode
...
Однако, если абонент вашей программы дает неверное число аргументов, это вызовет неясную ошибку времени выполнения (генерируемый fail
из сбой совпадения шаблонов). Более надежная программа может обрабатывать эти случаи с более подробными сообщениями об ошибках:
do
args <- getArgs
case args of
[] -> error "must supply a file to open"
[arg] -> do handle <- openFile arg ReadMode
...
_ -> error "too many arguments"