如何从 Haskell 中的字符串列表中获取搜索匹配项?
如何从 Haskell 中的字符串列表中获取搜索匹配项?
module Main
where
import List
import IO
import Monad
getLines = liftM lines . readFile
main = do
putStrLn "Please enter your name: "
name <- getLine
list <- getLines "list.txt"
-- mapM_ putStrLn list -- this part is to list out the input of lists
How do I get a search match from a list of strings in Haskell?
module Main
where
import List
import IO
import Monad
getLines = liftM lines . readFile
main = do
putStrLn "Please enter your name: "
name <- getLine
list <- getLines "list.txt"
-- mapM_ putStrLn list -- this part is to list out the input of lists
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
首先要做的事情,也是最重要的首要原则,是尽可能多地从
main
或IO
中获取思想。main
应尽可能包含所有IO
,也许除了用您在模块中其他地方定义的纯术语装饰的IO
之外什么也不包含。您的 getLines 不必要地混合了它们。因此,为了解决这个问题,我们应该有一个类似的
main
,或者可能是
IO
与我们获得的所有其他内容的更严格的隔离:与“纯”术语一起:
无论哪种方式,我们现在都真正进入了 Haskell 领域:现在的问题是弄清楚纯函数:
应该是什么。
我们可以从一个简单的匹配函数开始:当第一个字符串出现在字符串列表中时,我们得到一个匹配:
或者我们可能想要规范化一点,以便我们给出的名称的开头和结尾处有空格,并且列表中的名称不会影响匹配。这是一种相当简陋的方法:
然后我们可以改进旧的
match
,即elem
:现在我们需要遵循类型,弄清楚如何适应类型比如说
matchClean:: String -> [字符串] -> Bool
与frankJ :: String ->字符串 ->字符串
。我们希望将其放入frankJ
的定义中。因此,为了为
matchClean
'提供输入',我们需要一个函数来将我们从带有换行符的长字符串带到matchClean
需要的字符串(名称)列表:这就是 Prelude 函数lines
。但我们还需要决定如何处理
matchClean
生成的Bool
作为值;正如我们所知,frankJ
返回一个String
。让我们继续简单地分解问题:现在我们有了可以组合成函数
frankJ :: String ->; 的合理候选者的材料。字符串 ->我们要输入到
:main
中定义的IO
机器的字符串所以在这里,几乎所有事情都是纯函数的问题,很容易看出如何修正事物以进一步完善。例如,也许输入的名称和文本文件的行应该进一步规范化。在比较之前,内部空间应限制为一个空间。或者列表中的行中可能有一个逗号,因为人们被列为“姓氏,名字”等。或者也许我们希望响应函数使用该人的名字:
连同
当然有一百万种方法关于这个。例如,有
regex
库。 Hackage 中优秀且简单的Data.List.Split
也可能有用,但我不确定它是否可以被 Hugs 使用,您可能正在使用 Hugs。我注意到您对导入的模块使用旧式名称。我编写的内容仅使用 Prelude,因此不需要导入,但其他模块现在根据分层命名系统称为“System.IO”、“Data.List”和“Control.Monad”。我想知道您是否使用旧的教程或手册。也许令人愉快的“Learn You a Haskell”网站会更好?他确认他正在使用 ghc,但我认为这不会产生太大影响。
The first thing to do, the all-important first principle, is to get as much of the thinking out of
main
or out ofIO
as possible.main
should where possible contain all theIO
and maybe nothing butIO
decorated with pure terms you define elsewhere in the module. YourgetLines
is mixing them unnecessarily.So, to get that out of the way, we should have a
main
that is something like-- or maybe the more austere segregation of
IO
from all else that we get from:together with the 'pure' terms:
Either way, we are now really in Haskell-land: the problem is now to figure out what the pure function:
should be.
We might start with a simple matching function: we get a match when the first string appears on a list of strings:
or we might want to normalize a bit, so that white space at the beginning and end of the name we are given and the names on the list doesn't affect the match. Here's a rather shabby way to do that:
Then we can improve on our old
match
, i.e.elem
:Now we need to follow the types, figuring out how to fit the type of, say,
matchClean:: String -> [String] -> Bool
with that offrankJ :: String -> String -> String
. We want to fit it inside our definition offrankJ
.Thus, to 'provide input' for
matchClean
, we need a function to take us from a long string with newlines to the list of stings (the names) thatmatchClean
needs: that's the Prelude functionlines
.But we also need to decide what to do with the
Bool
thatmatchClean
yields as value;frankJ
, as we have it, returns aString
. Let us continue with simple-minded decomposition of the problem:Now we have materials we can compose into a reasonable candidate for the function
frankJ :: String -> String -> String
that we are feeding into ourIO
machine defined inmain
:So here, almost everything is a matter of pure functions, and it is easy to see how to emend things for further refinement. For example, maybe the name entered and the lines of the text file should be further normalized. Internals spaces should be restricted to one space, before the comparison. Or maybe there is a comma in lines on the list since people are listed as "lastname, firstname", etc. etc. Or maybe we want the response function to use the person's name:
together with
Of course there are a million ways of going about this. For example, there are
regex
libraries. The excellent and simpleData.List.Split
from Hackage might also be of use, but I'm not sure it can be used by Hugs, which you might be using.I note that you are using old-fashioned names for the imported modules. What I have written uses only the Prelude so imports are unnecessary, but the other modules are now called "System.IO", "Data.List" and "Control.Monad" in accordance with the hierarhical naming system. I wonder if you are using an old tutorial or manual. Maybe the pleasant 'Learn You a Haskell' site would be better? He affirms he's using
ghc
but I think that won't affect much.如果您不需要 list.txt 中包含该名称的所有行的列表,
您可以简单地使用
,但我不确定我是否正确理解您的问题。
If you wan't a list of all lines in your list.txt that contain the name,
you can simply use
but I'm not sure if I understood your question correct.