【发布时间】:2019-04-15 01:08:51
【问题描述】:
我正在查看来自the Haskell Wikibook 的简单 IO 程序。该页面上显示的结构工作得很好,但我试图理解“如何”。
下面的writeChar 函数接受文件路径(作为字符串)和字符,并将字符写入给定路径的文件。该函数使用bracket 来确保文件正确打开和关闭。在括号中运行的三个计算中,“中间运行的计算”——据我所知——是一个 lambda 函数,它返回 hPutChar h c 的结果。
现在,hPutChar 本身有一个 hPutChar :: Handle -> Char -> IO () 的声明。这就是我迷路的地方。我似乎将h 作为hPutChar 的句柄传递。我希望一个句柄以某种方式引用以fp 打开的文件,但它似乎是递归调用 lambda 函数\h。我不明白这个调用自身的 lambda 函数如何知道将c 写入fp 的文件。
我想了解为什么这个函数的最后一行不应该是(\h -> hPutChar fp c)。尝试以这种方式运行它会导致“无法将类型‘[Char]’与‘Handle’匹配”,考虑到 hPutChar 需要 Handle 数据类型而不是字符串,我认为这是明智的。
import Control.Exception
writeChar :: FilePath -> Char -> IO ()
writeChar fp c =
bracket
(openFile fp WriteMode)
hClose
(\h -> hPutChar h c)
【问题讨论】:
-
fp是一个 FilePath(实际上只是一个字符串)。 lambda 表达式中的h是Handle,它位于openFile返回的IO monad 中。见hackage.haskell.org/package/base-4.12.0.0/docs/System-IO.html。 -
\h本身并不是一个真正的实体;它只是 lambda 函数\h -> hPutChar fp c的一部分。 -
我误导自己认为同一行上的
h和\h指的是同一个实体! -
在 cmets 中保持参与和交谈的重要性:感谢您的上述评论,您的误解(“
\h”本身就是一个实体)终于变得清晰并且可以解决! /++
标签: haskell lambda syntax functional-programming io-monad