2009-12-21 89 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