【发布时间】:2019-12-22 19:06:13
【问题描述】:
我正在阅读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 等),但没有成功。
我一直在经历的一些稀疏的想法:
- lambda
(\c -> c == '\n' || c == '\r')对于这样一个简单而具体的任务来说功能太强大而表达能力太低了; - 此外,它包含大量重复代码和/或冗长无用。
- 无论我在
isCRorNL中输入什么,都必须输入Char -> Bool, - 因此,如果我为其提供第一个
n参数,它可以具有任何类型a1 -> a2 -> ... -> an -> Char -> Bool。 -
any函数可以帮助我检查 given 字符是'\n'还是'\r',或者换句话说,它是否在Chars @ 的列表中987654338@. - 由于我想检查是否相等,我可以将
(==)传递给我的函数。 - 因此
isCRorNL可以具有(Char -> Char -> Bool) -> [Char] -> Char -> Bool类型(或将前两个参数反转),我可以将(==)作为第一个参数传递给它,"\n\r"作为第二个参数传递给它。 - 所以我一直在寻找一些我可以编写的标准函数来获得这样的函数。
最后我放弃了,这样定义:isCRorNL e = any (== e) "\n\r";我认为这在可扩展性方面非常好,因为我可以在"…" 中添加尽可能多的字符,并且我可以更改运算符==;可悲的是,我不能将函数直接放在使用它的地方,因为我无法将其编写为部分应用的函数。
你会怎么做?
【问题讨论】:
标签: haskell functional-programming currying