mtt*_*pgn 0 syntax lambda haskell functional-programming io-monad
我正在从Haskell Wikibook看一个简单的IO程序。该页面上显示的构造效果很好,但是我试图理解“如何”。
writeChar下面的函数采用一个文件路径(作为字符串)和一个字符,并将该字符写入给定路径的文件中。该函数使用括号来确保文件正确打开和关闭。在方括号中进行的三个计算中,“在中间进行运算”(据我所知)是一个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)
Run Code Online (Sandbox Code Playgroud)
让我们看一下bracket(在Haskell Wiki链接中所引用的类型)的类型:
bracket :: IO a -- computation to run first ("acquire resource")
-> (a -> IO b) -- computation to run last ("release resource")
-> (a -> IO c) -- computation to run in-between
-> IO c
Run Code Online (Sandbox Code Playgroud)
在您的用例中,第一个参数openFile fp WriteMode是一个IO Handle值,一个产生对应于fp路径的句柄的计算。第三个参数,\h -> hPutChar h c是一个具有句柄并返回写入其中的计算的函数。这个想法是您作为第三个参数传递的函数指定了如何使用第一个参数产生的资源。