我一直在审查Haskell Hierarchical库中的这段代码片段。 我可以按照下面代码的大部分片段,但是“。” (函数组合)在这种情况下的行为抛出了我,因为我期望参数为foldr,特别是:foldr f z list。我将parseLine视为f,z视为M.empty,将行视为列表。所以我希望我的混淆是关于函数组合和where子句的行为。当我尝试从Haskell中理解时,任何理解这个函数的帮助都会非常受欢迎。
-- Parse the file we've just read in, by converting it to a list of lines,
-- then folding down this list, starting with an empty map and adding the
-- username and password for each line at each stage.
parseMap :: String -> PassDB
parseMap = foldr parseLine M.empty . lines
where parseLine ln map =
let [un, pw] = words ln
in M.insert un pw map
答案 0 :(得分:3)
您必须将此表达式解析为(foldr parseLine M.empty) . (lines)
。因此,parseLine
和M.empty
是foldr
的第一个和第二个参数,你是对的。但是,lines
不是foldr
的参数。
所以foldr
仍然缺少一个参数,即foldr parseLine M.empty
是类型[String] -> PassDB
的函数。并且lines
也缺少一个参数,它是来自String -> [String]
的函数。这就是.
在这里组成的两个功能。所以我们一起得到String -> PassDB
类型的函数。
请注意,参数仍然缺失,因此parseMap
是一个函数。正如它的类型注释所说的那样。
答案 1 :(得分:2)
首先我应该说,在Haskell中,所有函数都采用一个参数。这就是currying,这就是你发布的语法。
然后,此语法是pointfree样式的实例。您可以按照以下方式阅读它:
parseMap :: String -> PassDB
parseMap s = foldr parseLine M.empty . lines $ s
where parseLine ln map =
let [un, pw] = words ln
in M.insert un pw map
从上面的表单转到您发布的表单称为执行eta-reduction。
当您可以执行eta-reduction时,可以通过将hlint(例如emacs与haskell-mode)集成的智能编辑器向您发出警告。
当你理解了这一切之后,理解函数组合只是意识到输入字符串将首先作为输入提供给lines
,该函数将把字符串转换为列表,然后是结果列表将提供给foldr
。