【问题标题】:Haskell ReadFile fails for existing filesHaskell ReadFile 对现有文件失败
【发布时间】:2026-01-04 23:20:10
【问题描述】:

我在 Haskell 中编写一个函数作为编译器的一部分来打开一个文件,从中读取一组文件名并将它们连接成一个字符串。该代码在 ghci 中运行良好,但在使用以下内容编译时失败:

fact.fn: openFile: 不存在(没有这样的文件或目录)

我完全确定 fact.fn 存在并且它与可执行文件位于同一目录中。

相关代码:

compile [fileName] = do  
             (ilude, contents) <- imports fileName
             let lude = "prelude.fn" : ilude
             prld <- fmap fullPrelude (mapM readFile lude) --seems to fail here, 
--but works fine in the interpreter
             let newPrld = unlines [prld, "\nend"]
             runEvalWith HappyParser.parseExpr fileName contents newPrld


imports :: String -> IO ([String], String)
imports fileName = do 
    contents <- readFile fileName
    let ls = lines contents
    let ifile = filter (isPrefixOf "import") ls {-find import string here-}
    let contentList = filter (\w -> w `notElem` ifile) ls
    let impts = mapMaybe (stripPrefix "import") ifile
    return (impts, (unlines contentList) )


fullPrelude :: [String] -> String
fullPrelude [] = ""
fullPrelude xs = unlines( map (procPrelude) xs)

procPrelude :: String -> String
procPrelude pld = unlines(init(words pld))

【问题讨论】:

  • 你是在同一个目录下运行的吗?可执行文件的位置无关紧要:它采用pwd 并将文件名添加到其中。
  • 除了 Willem 的评论 - 如果您在 Windows 上:如果在 PowerShell 上 pwd 被预定义为 Get-Location 的别名,它返回当前位置。在 CMD pwd 不可用时,要获取当前目录运行 cd(不带任何参数)。
  • 我在 Ubuntu 上,我确实在同一个目录中运行。我什至复制到新目录以检查权限。

标签: haskell readfile io-monad


【解决方案1】:

我认为问题在于,在处理如下导入命令时:

import fact.fn

您并没有从文件名的开头删除空格,因此您的程序实际上是在尝试导入文件" fact.fn" 而不是"fact.fn"。如果您仔细研究错误消息,您可以验证是否属于这种情况。如果错误是:

*** Exception:  fact.fn: openFile: does not exist (No such file or directory)

Exception:fact.fn 之间有两个空格而不是一个空格,那么文件名的开头会有一个额外的空格。

我完全不知道你是如何在解释器中成功运行它的。

【讨论】:

  • 非常感谢!!感觉就像我错过了一个完全的菜鸟工作。