Haskell:从文件读取变量

时间:2017-06-16 11:43:20

标签: haskell

我在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"。我该怎么做,将数据从文件读取到变量?

1 个答案:

答案 0 :(得分:1)

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

  • ()通知我们该功能是不纯的
  • main告诉我们它没有返回数据

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

当你可以更改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}}

那会更容易,但我不确定这是否是您的总体目标......