Haskell程序中的类型错误
用户可以给出id、宽度、高度和描述矩形,然后我将其写入文件。现在,我想将此内容从文件加载到我的程序,但出现错误: 无法将预期类型[RectangleType]与推断类型IO[RectangleType]匹配。在menuRectangles的第一个参数中,即db。在表达式菜单中,选择“矩形”。在do表达式中,menuRectangles db 发生了什么事?这是我的文件的内容: [矩形2 5 6“abcabc”,矩形1 2 4“abcabc”] 这是代码:Haskell程序中的类型错误,haskell,io,monads,Haskell,Io,Monads,用户可以给出id、宽度、高度和描述矩形,然后我将其写入文件。现在,我想将此内容从文件加载到我的程序,但出现错误: 无法将预期类型[RectangleType]与推断类型IO[RectangleType]匹配。在menuRectangles的第一个参数中,即db。在表达式菜单中,选择“矩形”。在do表达式中,menuRectangles db 发生了什么事?这是我的文件的内容: [矩形2 5 6“abcabc”,矩形1 2 4“abcabc”] 这是代码: import IO import Cha
import IO
import Char
import System.Exit
import Maybe
data RectangleType = Rectangle Int Int Int deriving(Show, Read)
loadFile :: FilePath -> IO [RectangleType]
loadFile fname =
catch (do fileContent <- readFile fname
return (read fileContent)
) errorHandler
where
errorHandler e = do putStrLn ("Error file")
exitFailure
db = loadFile "db.txt"
main = do
putStrLn "Choose option:"
n <- getLine
case n of
"1" -> do menuRectangles db; main
"2" -> putStrLn "bye, bye"
otherwise -> do putStrLn "Bad option"; main
menuRectangles :: [RectangleType] -> IO [RectangleType]
menuRectangles rs = do
putStrLn "Please choose option:"
putStrLn "1 - Add rectangle"
putStrLn "2 - Show rectangle"
putStrLn "3 - Quit"
putStr "Number: "
n <- getLine
case n of
"1" -> do { {- rs_new <- addRectangle rs; -} menuRectangles rs };
"2" -> do { {- showRectangle rs; -} menuRectangles rs }
"3" -> do { putStrLn "Quitting"; return rs }
otherwise -> do { putStrLn "The End"; return rs }
导入IO
导入字符
导入系统。退出
也许是进口
数据矩形类型=矩形整数派生(显示,读取)
loadFile::FilePath->IO[矩形类型]
加载文件fname=
捕获(不执行文件内容输入)“再见,再见”
否则->执行putStrLn“坏选项”;主
menuRectangles::[RectangleType]->IO[RectangleType]
menuRectangles rs=do
putStrLn“请选择选项:”
putStrLn“1-添加矩形”
putStrLn“2-显示矩形”
putStrLn“3-退出”
putStr“编号:”
n do{-rs_新do{-showtrectangles rs;-}menuRectangles rs}
“3”->do{putStrLn“退出”;返回rs}
否则->执行{putStrLn“结束”;返回rs}
编辑:
正确代码:
import IO
import Char
import System.Exit
import Maybe
data RectangleType = Rectangle Int Int Int deriving(Show, Read)
loadFile :: FilePath -> IO [RectangleType]
loadFile fname =
catch (do fileContent <- readFile fname
return (read fileContent)
) errorHandler
where
errorHandler e = do putStrLn ("Error file")
exitFailure
main = do
db <- loadFile "db.txt"
mainMenu db
mainMenu rs = do
putStrLn "Choose option:"
n <- getLine
case n of
"1" -> do menuRectangles rs; mainMenu rs
"2" -> putStrLn "bye, bye"
otherwise -> do putStrLn "Bad option"; mainMenu rs
menuRectangles :: [RectangleType] -> IO [RectangleType]
menuRectangles rs = do
putStrLn "Please choose option:"
putStrLn "1 - Add rectangle"
putStrLn "2 - Show rectangle"
putStrLn "3 - Quit"
putStr "Number: "
n <- getLine
case n of
"1" -> do { {- rs_new <- addRectangle rs; -} menuRectangles rs };
"2" -> do { {- showRectangle rs; -} menuRectangles rs }
"3" -> do { putStrLn "Quitting"; return rs }
otherwise -> do { putStrLn "The End"; return rs }
导入IO
导入字符
导入系统。退出
也许是进口
数据矩形类型=矩形整数派生(显示,读取)
loadFile::FilePath->IO[矩形类型]
加载文件fname=
catch(不做文件内容不做putStrLn“坏选项”;主菜单
menuRectangles::[RectangleType]->IO[RectangleType]
menuRectangles rs=do
putStrLn“请选择选项:”
putStrLn“1-添加矩形”
putStrLn“2-显示矩形”
putStrLn“3-退出”
putStr“编号:”
n do{-rs_新do{-showtrectangles rs;-}menuRectangles rs}
“3”->do{putStrLn“退出”;返回rs}
否则->执行{putStrLn“结束”;返回rs}
在Haskell中存在一个称为纯代码的概念。纯代码不包含以下任何内容:用户输入值、系统调用、伪随机数生成、对非纯代码的调用等
基于程序的词法内容,纯函数保证始终具有相同的行为(例如,它们可以返回不同的值,但返回不同值的原因不能取决于“世界”)
在函数式语言中,这是一个非常强大的策略,允许编写非常强大的代码。例如,您知道调用函数不会改变一些不相关的全局变量或其他数据结构的状态。我经常将此策略应用于python代码
哈斯凯尔强化纯度和杂质的方式是用IO单子
“世界”涉及的任何事物都被包装在IO monad中,表示这些值已被“污染”。如果任何事物涉及这些“污染”值,它们返回的值也必须被污染
如果您想让IO monad访问这些值,您需要在IO monad中运行纯代码。在IO monad中,您可以“展开”读取的值并将其传递到纯代码中,然后纯代码返回值,然后您可以打印值。所有操作都按预期进行,但您必须在IO monad中执行
请注意,确保大多数代码都是以IO单子外部的纯函数形式编写的是一种很好的形式。例如,纯dostuff with rectangles
函数,然后从IO单子内部调用该函数
它的美妙之处在于,您的纯代码不需要知道矩形
值已被IO矩形
类型所污染。只要您在IO monad中工作,您的纯代码就会认为它只是一个普通的矩形
为了更明确地回答这个问题:
readFile
返回封装在IO monad中的内容,因为这些内容来自“世界”(文件系统),例如,如果您在程序执行期间更改了文件,它可能会返回不同的值
--db = loadFile "db.txt" REMOVED--
main = do --within the IO monad
putStrLn "Choose option:"
n <- getLine
**DB <- LOADFILE "db.txt"** --db is now a pure value
case n of
"1" -> do menuRectangles db; main
"2" -> putStrLn "bye, bye"
otherwise -> do putStrLn "Bad option"; main
--db=loadFile“db.txt”已删除--
main=do——在IO monad中
putStrLn“选择选项:”
“再见,再见”
否则->执行putStrLn“坏选项”;主
更多信息:
一个好的在线/办公室文件阅读:
还有一个很好的在线/办公室文件阅读:据我从问题中看到,OP已经知道IO的概念。也许他只是忘记了那个单一的签名。ninjagecko不幸的是,你的代码对我不起作用。我已经更改了我的代码,现在它可以工作了(不幸的是,我不知道如何在注释中编写代码-为什么所有代码都在一行?):
main=do db putstrn“bye,bye”否则->do putstrn“坏选项”;main menu rs
我想你已经知道我添加的那行了**DB为什么错误的代码还在帖子中?大概是为了让问题和答案仍然有意义。