2017-06-16 53 views
-2

我有下面的代码在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 []) = [] 

我运行主选择与Plaster实例的单实例文件路径。然后我想申请功能getFirst(我希望)变量plaster2,但我收到:"Variable not in scope: plaster2"。我该怎么做,从文件读取数据到变量?

+0

作为贴在这里,代码不编译:简单地用各种Plaster值调用它GHCI ,但不包含OP中报告的错误消息。请重新发布代码,确保格式正确,因为Haskell使用重要的空白。 –

+0

@MarkSeemann谢谢你提到这一点。现在它应该正确编译。 – Czarek

+0

确实,它现在编译。但是,这也意味着它不会产生报告的编译器错误。 –

回答

1

在OP中,main定义了函数,其类型为IO()。这基本上意味着两件事情:

  • IO告诉我们,该函数是不纯的
  • ()告诉我们,它没有返回数据

main定义的所有命名值仅是函数中使用。我们说他们是范围main函数。它们在功能之外是无法访问的。这不仅适用于plaster2,也适用于path,opennplaster1

虽然你可能更改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 

即使我试图清理代码位,仍然有问题与它,但我不想混淆你与目前。

您可以加载GHCI你的代码,并开始与该功能交互,还有getFirst功能:

*Answer> plaster2 <- readFirstLineInFile 
Please choose path: 
ploeh.txt 
*Answer> getFirst plaster2 
"foo" 

在这里,我开始readFirstLineInFile,而它的返回值绑定到plaster2。完成交互并输入ploeh.txt后,readFirstLineInFile函数返回,并且plaster2有值。

我现在可以拨打getFirstplaster2,并验证结果是否符合预期。

但是,如果您的总体目标是能够交互式测试getFirst,则无需使其变得如此复杂;

*Answer> getFirst $ Plaster ["foo", "bar"] 
"foo" 
*Answer> getFirst $ Plaster ["foo"] 
"foo" 
*Answer> getFirst $ Plaster [] 
"" 

这将是很容易,但我不知道这是你的总体目标......