Parsing 为什么Haskell';s类型系统在使用readFile时有问题吗?
我对Haskell的打字系统有一些问题 情况:Parsing 为什么Haskell';s类型系统在使用readFile时有问题吗?,parsing,haskell,types,readfile,Parsing,Haskell,Types,Readfile,我对Haskell的打字系统有一些问题 情况: 下面的程序在命令行上获取文件名列表 对于每个文件名,使用函数readFile 每个文件的内容都被传递到inputParser(来自Parsec库) 休息并不那么重要 主要问题在于功能读取模块 do表达式的前两个语句在Haskell的类型系统中无效 问题是[String]与IO String与[Char]与 函数parse应该接受一个字符串,但是当它得到它时,它突然想要一个IO字符串(作为同一个参数),否则它想要一个字符串 我想要什么: 读取每个
- 下面的程序在命令行上获取文件名列表
- 对于每个文件名,使用函数
readFile
- 每个文件的内容都被传递到
(来自Parsec库)inputParser
- 休息并不那么重要
- 主要问题在于功能
读取模块
表达式的前两个语句在Haskell的类型系统中无效do
- 问题是
与[String]
与IO String
与[Char]
- 函数
应该接受一个parse
,但是当它得到它时,它突然想要一个字符串
(作为同一个参数),否则它想要一个IO字符串
字符串
parse
函数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
modulemain其中
导入系统.IO
导入系统。环境
导入Text.ParserCombinators.Parsec
导入输入解析器
导入数据
用法::IO()
用法=putStrLn“用法:x文件选项”
parse_modules::String->[Char]->ParseError[Module]
parse_modules filename input=parse inputParser filename input
读取模块::[String]->[Module]
读取模块[]=[]::[模块]
读取模块(文件名:rest)=
做
内容输出++(读取模块rest)
返回模块
用法::[String]->IO()
使用args=
做
这是错误的
read_modules :: [String] -> [Module]
应该是
read_modules :: [String] -> IO [Module]
这并不是您需要解决的全部问题,但它会让您继续前进。这是错误的
read_modules :: [String] -> [Module]
应该是
read_modules :: [String] -> IO [Module]
这并不是您需要解决的全部问题,但它会帮助您解决问题。首先,由于您的函数读取模块执行I/O,因此它必须返回类型为IO
的内容。这意味着您必须更改函数中的许多内容:
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
空箱子必须使用return
case表达式中的Right
分支必须使用do表示法
当递归调用自身时,函数必须在do表示法中这样做
这里有一个(希望是)您的read\u模块的固定版本
函数:
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
read_模块::[String]->IO[Module]
读取模块[]=返回[]
读取模块(文件名:rest)=
做
知足
更多首先,由于您的函数read\u模块执行I/O,它必须返回IO
类型的内容。这意味着您必须更改函数中的许多内容:
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
空箱子必须使用return
case表达式中的Right
分支必须使用do表示法
当递归调用自身时,函数必须在do表示法中这样做
这里有一个(希望是)您的read\u模块的固定版本
函数:
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
read_模块::[String]->IO[Module]
读取模块[]=返回[]
读取模块(文件名:rest)=
做
知足
更多以下是导致您所说的不太重要的另一个错误的原因:
use :: [String] -> IO ()
use args =
do
init <- last args
看起来你在其他几个地方也犯了同样的错误,不仅仅是那一行。当您只想在函数中创建一个临时变量时,必须像这样以不同的方式对待一元值和非一元值,这对于初学这门语言的人来说是一件容易混淆的事情
顺便说一下,init
是标准库中函数的名称,因此您可能需要使用不同的变量名。以下是导致您所说的其他不太重要的错误的原因:
use :: [String] -> IO ()
use args =
do
init <- last args
看起来你在其他几个地方也犯了同样的错误,不仅仅是那一行。当您只想在函数中创建一个临时变量时,必须像这样以不同的方式对待一元值和非一元值,这对于初学这门语言的人来说是一件容易混淆的事情
顺便说一句,init
是标准库中的函数名,因此您可能需要使用不同的变量名。您的答案并不完全是我想听到的,但在我阅读了更多关于monad的内容以及在IO
中涉及简单函数时,它可能会有所帮助(目前)不过,如果你考虑一下,作为我之前评论的一个警告,那肯定是过于简单化了,所以不要太直截了当。你的答案并不完全是我想听到的,但在我读了更多关于monad的内容之后,当谈到IO
中的简单函数时,它可能会有所帮助(现在)但是,如果你考虑一下,作为对我之前评论的一个警告,这绝对是一个过于简单化的说法,所以不要太直截了当。谢谢你提到IO。那是个大错误。谢谢你提到IO。这是最大的错误。