我正在阅读 Real World Haskell ,我尝试实现 splitLines
自己编写代码,我想出了或多或少相同的实现(Chapter 4,第 73 页):
splitLines :: String -> [String]
splitLines [] = []
splitLines ('\r':a) = splitLines a
splitLines ('\n':a) = splitLines a
splitLines a = let (l,r) = break isCRorNL a
in l:splitLines r
where isCRorNL e = ???
--the book defines isCRorNL c = c == '\n' || c == '\r'
但是,我确实花费了太多时间来尝试编写
isCRorNL
以我能想到的最实用和最易读的方式,这样我就可以摆脱 where
并转动 splitLines
的最后一个定义变成一个最接近英语的句子(就像 compare `on` length
等),但没有成功。我一直在经历的一些稀疏的想法:
(\c -> c == '\n' || c == '\r')
,对于这样一个简单而具体的任务来说,只是太多的力量和太少的表现力; isCRorNL
必须有类型 Char -> Bool
, a1 -> a2 -> ... -> an -> Char -> Bool
如果我提供第一个 n
论据。 any
函数可以帮助我检查给定字符是否为 '\n'
或 '\r'
或者,换句话说,如果它在 Char
的列表中小号 "\n\r"
. (==)
到我的功能。 isCRorNL
可以有类型 (Char -> Char -> Bool) -> [Char] -> Char -> Bool
(或将前两个参数倒置),我可以传递给它 (==)
作为第一个参数和 "\n\r"
作为第二个论点。 最后我放弃了,这样定义:
isCRorNL e = any (== e) "\n\r"
;我认为这在可扩展性方面非常好,因为我可以在 "…"
中添加尽可能多的字符,我可以更改运算符 ==
;可悲的是,我不能将函数直接放在使用它的地方,因为我无法将其编写为部分应用的函数。你会怎么做?
最佳答案
当我在问题中查找链接并访问它(第一次)时,我意识到代码块是由读者评论的,而 splitLines
下的第一条评论阅读:
augustss 2008-04-23
[...] If you're making a point about functional style maybe you should use
isLineSeparator = (`elem` "\r\n")
因此,我对函数的组合思考了很多,而最简单的解决方案在于部分应用一个如此简单的函数,
elem
.这里的缺点是用于检查相等性的运算符是内置在 elem
中的。并且无法更改。尽管如此,我还是因为没有想到 elem
而感到愚蠢。我。
关于haskell - 一元谓词检查字符串中的字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59338559/