2016-04-25 57 views
2

即时尝试制作一个应该逐行读取文件的程序,并检查它是否为palindrom,如果是,则打印。如何从Haskell中的一个文件逐行读取

我真的很新的哈斯克尔,所以我唯一可以做的事情就是刚刚打印出的每一行,使用此代码:

main :: IO() 
    main = do 
    filecontent <- readFile "palindrom.txt" 
    mapM_ putStrLn (lines filecontent) 

isPalindrom w = w==reverse w 

的事情是,我不知道如何通过线走线和检查行是否是一个回文(请注意,在我的文件中,每行只包含一个字)。谢谢你的帮助。

回答

3

看看filter函数。您可能不希望将所有处理放在一行上,但使用表达式。另外,你的缩进熄灭:

main :: IO() 
main = do 
    filecontent <- readFile "palindrom.txt" 
    let selected = filter ... filecontent 
    ... 
+0

你能写出完整的代码吗?即时通讯绝对是新的,所以我不知道如何继续.. –

2

这里有一个建议的方法

main :: IO() 
main = do 
    filecontent <- readFile "palindrom.txt" 
    putStrLn (unlines $ filter isPalindrome $ lines filecontent) 

isPalindrome w = w==reverse w 

括号中的部分是纯粹的代码,它的类型是String->String。尽可能多地分离纯代码通常是一个好主意,因为代码往往是最容易推理的,并且通常更容易重用。

您可以将该部分中的数据视为从右向左流动,由($)运算符分解。首先你将内容分成不同的行,然后只过滤回文,最后以字符串的形式重建完整的输出。另外,由于Haskell是懒惰的,即使它看起来像是将内存中的输入视为单个String,但实际上它只是根据需要提取数据。


编辑以添加额外的信息....

OK,所以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)。在我们的案例中,第一项和第三项实际上是古典的,第二项没有。我们的表达式的计算结果如下

unlines ["abcba", "K"] 

最后,unlineslines相反....它将再次concatinate的项目,在间插入换行。

"abcba\nK" 

由于STDIO本身是String,因此可以输出。

注意,是它完美地确定以输出的使用非纯函数String秒的列表,如下所示

forM ["1", "2", "3"] $ \item -> do 
    putStrLn item 

然而,该方法混合纯和不纯的代码,并且被认为是略小于惯用Haskell代码比前者。尽管如此,你仍然会看到这种类型的东西!

+0

嗨,感谢您的帮助,请你解释一下关于“$”操作符和函数过滤器如何工作? 据我了解,过滤器检查,如果“isPalindrome”在filecontents的每一行,如果属实,那么打印,对不对?那么,为什么我需要在这里不成立? 非常感谢! –

+1

我已经添加了更多细节。 – jamshidh

+0

太好了! , 谢谢 ! –