1

Haskellの型システムに問題があります。

状況:

  • 次のプログラムは、コマンドラインでファイル名のリストを取得しています
  • ファイル名ごとに、その内容が関数を使用して読み取られますreadFile
  • inputParser各ファイルの内容は(Parsecライブラリから)に渡されます
  • 休息はそれほど重要ではありません
  • 主な問題は機能にありますread_modules
  • 式の最初の2つのステートメントは、doHaskellの型システムでは無効です。
  • 問題はvsvsvs..間の[String]競合IO Stringです[Char]
  • 関数parseは取る必要がありますStringが、それを取得すると、IO String突然(同じ引数として)必要になります。それ以外の場合は、String

私が欲しいものは:

  1. 各ファイルの内容を読む
  2. parseそのコンテンツを3番目の引数として関数に渡します

コードは次のとおりです。

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

何が問題ですか:

  • 何をどこに渡すべきか理解できません-何が欲しいかはある程度わかっていますが、構文やスタイルがわかりません。
  • Haskellは初めてです。
  • Haskellのタイプ...

質問は何ですか:

  • 提示されたタイプの問題を修正するにはどうすればよいですか?
  • 私は何を入れるべきですかparse-何readFileが私に与えますか?
  • タイプは互換性がありますか?
  • ある種の変換は必要ありませんか?

関連するウェブリンク:

ヒントやコメントありがとうございます。

4

3 に答える 3

4

まず、関数read_moduleはI / Oを実行するため、タイプの何かを返す必要がありIOます。つまり、関数内のいくつかのことを変更する必要があります。

  1. 空のケースは使用する必要がありますreturn
  2. Rightcase式のブランチはdo-notationを使用する必要があります
  3. 自分自身を再帰的に呼び出す場合、関数はdo表記内で呼び出す必要があります

これが(うまくいけば)read_modules関数の修正バージョンです:

read_modules :: [String] -> IO [Module]
read_modules [] = return []
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 -> do 
        more <- read_modules rest
        return (out ++ more)
    return modules

私はそれをテストしていませんが、それが途中であなたを助けることを願っています。

于 2009-12-21T19:14:55.807 に答える
3

これは間違っています。

read_modules :: [String] -> [Module]

する必要があります

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

修正する必要があるのはそれだけではありませんが、それで問題は解決します。

于 2009-12-21T19:14:50.643 に答える