这是一种建议的方法
main :: IO()
main = do
filecontent <- readFile "palindrom.txt"
putStrLn (unlines $ filter isPalindrome $ lines filecontent)
isPalindrome w = w==reverse w
括号中的部分是纯代码,类型为String->String。尽可能多地隔离纯代码通常是一个好主意,因为这些代码往往是最容易推理的,而且通常更容易重用。
您可以认为数据在该部分中从右向左流动,由($) 运算符分隔。首先将内容拆分为单独的行,然后仅过滤回文,最后将完整输出重建为字符串。此外,由于 Haskell 是惰性的,即使它看起来像是将输入视为内存中的单个 String,但实际上它只是根据需要拉取数据。
已编辑以添加额外信息....
好的,所以soln的核心是纯净的部分:
unlines $ filter isPalindrome $ lines filecontent
($) 的工作方式是评估右侧的函数,然后将其用作左侧内容的输入。在这种情况下,filecontent 是文件的完整输入(String,包括换行符),输出是 STDOUT(也是一个完整的字符串,包括换行符)。
让我们通过这个过程跟踪示例输入,“abcba\n1234\nK”
unlines $ filter isPalindrome $ lines "abcba\n1234\nK"
首先,行将其分解为行数组
unlines $ filter isPalindrome ["abcba", "1234", "K"]
请注意,行的输出被输入到过滤器的输入中。
那么,过滤器有什么作用?注意它的类型
filter :: (a -> Bool) -> [a] -> [a]
这需要 2 个输入参数,第一个是一个函数(isPalendrome 是),第二个是项目列表。它将使用该函数测试列表中的每个项目,其输出是相同的列表输入,减去该函数选择删除的项目(返回False on)。在我们的例子中,第一项和第三项实际上是古文,第二项不是。我们的表达式计算如下
unlines ["abcba", "K"]
最后,unlines 是 lines 的反面......它将再次连接项目,在其间插入换行符。
"abcba\nK"
由于 STDIO 本身是 String,因此可以输出。
注意,使用非纯函数输出Strings的列表是完全可以的,如下
forM ["1", "2", "3"] $ \item -> do
putStrLn item
然而,这种方法混合了纯代码和不纯代码,并且被认为比前者更不习惯 Haskell 代码。不过,您仍然会经常看到这种类型的东西!