2009-12-21 88 views
1

我对Haskell类型系统有一些麻烦。Haskell读取文件类型问题

现状:

  • 下面的程序走的文件名列表上CMDLINE
  • 对于所有的文件名读取使用功能READFILE每个文件的
  • 内容传递给inputParser其内容(秒差距)
  • 作息不那么重要
  • 主要问题是功能read_modules
  • 前两日'do'表达式在Haskell类型系统中是无效的
  • 问题在[String] x IO String x [Char] x ...
  • 之间有冲突,但是当函数'parse'它想IO字符串突然(在相同的参数),否则要字符串

我想要什么:

  1. 阅读每个文件的内容
  2. 传递内容的“解析”功能第三个参数

这是代码。

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 

这里是GHC输出错误

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 

是什么问题:

  • 我不明白我应该通过地方。我有点知道我想要什么,但我没有得到语法或风格。
  • 我哈斯克尔greenie(此处未解决)
  • 类型

什么问题:

  • 如何解决提出的问题类型?我应该把什么放入'解析'功能? 'readFile'给了我什么?这两种类型是兼容的吗?是否需要进行某种类型的转换?

相关网站链接:

谢谢大家的提示和评论。

回答

2

这里是什么导致其他错误,你说是不那么重要了:

use :: [String] -> IO() 
use args = 
    do 
    init <- last args 

<-运营商是一个do块内用于提取包含在一个单子的东西(在这种情况下,IO),这样你可以与里面的实际价值一起工作。但是,args这里的类型是[String],而不是IO [String],所以你不需要那样做;你已经从IO拉出了参数列表,其中主要为arg <- getArgs

如果你想分配非一元价值的do块的临时变量内,用let代替,就像这样:

let x = last args 

它看起来像你犯同样的错误在其他几个地方也是如此,而不仅仅是那条路线。必须以不同的方式处理monadic和非monadic的值,当你只是想在你的函数中创建一个临时变量时,很容易让一个新手对这个语言感到困惑。

顺便说一下,init是标准库中函数的名称,因此您可能需要使用不同的变量名称。

+0

你的回答并不完全是我想听到的,但是当我阅读了关于monads和< - 运算符的更多信息之后,我的确了解了我的代码中的许多缺陷。谢谢你指出真正的问题。 – Martin 2009-12-21 22:15:21

+1

当涉及IO中的简单函数时,如果你认为'<-'是“实现它”,那么它可能会有帮助(现在)。类型为'IO [String]'的东西表示“做一些I/O并接收一个字符串列表”的想法。一旦你用'<-'提取了值,你已经完成了实际的输入,现在你已经有了你的列表,所以除非你想获得更多的输入,否则你不应该使用另一个'<-'。 – 2009-12-22 00:52:16

+0

虽然,作为对我以前的评论的一个警告,这绝对是过于简单化,所以不要太字面。 – 2009-12-22 00:55:23

3

这是错误的。

read_modules :: [String] -> [Module] 

应该

read_modules :: [String] -> IO [Module] 

这还不是全部,你需要修复,但它将让你去。

4

首先,由于您的函数read_module s执行I/O,它必须返回类型IO。这意味着,你必须改变你的函数的一些事情:

  1. 空的情况下,必须使用return
  2. Right分支的情况下表达必须使用做标记法
  3. 当递归调用本身

    :函数必须在DO-符号

这里有一个(希望)固定的read_modules功能的版本内这样做

我还没有测试过,但我希望它能帮助你。

+0

谢谢你提到IO。这是主要的错误。 – Martin 2009-12-21 22:16:12