我在Haskell中有以下代码:
import System.IO
data Plaster = Plaster [String] deriving (Read, Show)
main = do putStrLn "Please choose path:"
path <- getLine
openn <- openFile path ReadMode
plaster1 <- hGetLine openn
let plaster2 = read plaster1::Plaster
putStrLn(plaster1)
getFirst :: Plaster -> String
getFirst (Plaster (x:xs)) = x
getFirst (Plaster []) = []
我运行main并选择具有Plaster
实例的单个示例的文件的路径。然后我想将函数getFirst
应用于(我希望)变量plaster2
,但我收到:"Variable not in scope: plaster2"
。我该怎么做,将数据从文件读取到变量?
答案 0 :(得分:1)
在OP中,IO ()
定义了函数,其类型为IO
。这基本上意味着两件事:
()
通知我们该功能是不纯的main
告诉我们它没有返回数据 main
中定义的所有命名值仅在该函数中可用。我们说它们范围到plaster2
函数。它们在功能之外是不可访问的。这不仅适用于path
,也适用于openn
,plaster1
和main
。
当你可以更改main
以便它返回一个值时,这将是非正统的; readFirstLineInFile :: IO Plaster
readFirstLineInFile = do
putStrLn "Please choose path:"
path <- getLine
h <- openFile path ReadMode
plaster1 <- hGetLine h
hClose h
return $ read plaster1
函数很特殊,因为这通常是应用程序的入口点。
相反,我建议你将你关心的行为提取到一个单独的(不纯的)函数中:
getFirst
尽管我试图稍微清理一下代码,但仍然存在问题,但我现在不想让你感到困惑。
您可以使用GHCI加载代码并开始与此函数进行交互,以及*Answer> plaster2 <- readFirstLineInFile
Please choose path:
ploeh.txt
*Answer> getFirst plaster2
"foo"
函数:
readFirstLineInFile
在此,我将plaster2
绑定到ploeh.txt
的返回值时启动readFirstLineInFile
。完成交互并输入plaster2
后,getFirst
函数返回,plaster2
有值。
我现在可以使用getFirst
致电Plaster
,并验证结果是否符合预期。
但是,如果您的总体目标是能够以交互方式测试*Answer> getFirst $ Plaster ["foo", "bar"]
"foo"
*Answer> getFirst $ Plaster ["foo"]
"foo"
*Answer> getFirst $ Plaster []
""
,那么您就不需要让它变得如此复杂;只需在GHCI中使用各种{{1}}值调用它:
{{1}}
那会更容易,但我不确定这是否是您的总体目标......