我是 Haskell 的新手,我创建了一个函数来允许“用户”将新电影添加到数据库(一个名为 Films.txt 的文本文件)。
main = do
putStrLn "Insert film title:"
film <- getLine
putStrLn ("Who directed " ++ film ++ "?")
director <- getLine
putStrLn ("What year was " ++ film ++ " released?")
year <- getLine
appendFile "Films.txt" $ (film ++ "\n")
appendFile "Films.txt" $ (director ++ "\n")
appendFile "Films.txt" $ (year ++ "\n")
appendFile "Films.txt" $ (" " ++ "\n")
创建的文本文件的一个例子是:
Blade Runner
Ridley Scott
1982
The Fly
David Cronenberg
1986
etc...
如果我只想返回某个导演的电影,我将如何逐行搜索该文件。在另一种语言中,我将使用 FOR 循环逐行搜索 .txt 文件,直到有一行与搜索词匹配,例如“Ridley Scott”。然后我将返回到匹配行上方的行,输出它(电影名称)并继续搜索,直到 .txt 文件完成。
但是在 Haskell 中,我无法将这个思维过程转换为代码,主要是因为我找不到逐行搜索文件的方法。
谢谢
使用您自己的方法,扫描文件以查找名称:
main = do
putStrLn "Enter Director's name"
name <- getLine
base <- readFile "Films.txt" -- base is the whole file contents as a single string
print $moviesBy name $lines base
moviesBy :: String -> [String] -> [[String]]
moviesBy name (title:director:year:_:others) | director == name = [title, director, year]:moviesBy name others
| otherwise = moviesBy name others -- a different director, scan the rest of the file
moviesBy _ _ = [] -- when there's no more records
更详细...
lines base
将文件内容按行拆分(删除换行符),生成字符串列表。
moviesBy
接受字符串作为搜索模式,以及作为文件内容的字符串列表。从这个文件是如何创建的,我们希望在每一个找到导演的名字第二行每四。这是作为第一个模式匹配完成的:
moviesBy name (title:director:year:_:others)
在这里,(title:director:year:_:others)
匹配一个至少包含四个元素的列表,将它们绑定到相关变量(_
第四个位置是一个通配符模式,这里与对我们无关紧要的空白字符串进行匹配)。others
,作为 最右边的操作数:
,因此匹配列表的剩余部分(第四个尾部,用 Lisp 的话)。在管道之后,|
我们在匹配上添加了一个额外的约束,四元组中的第二个元素应该等于关注的导演的名字。如果为 true,则将 的列表[title, director, year]
插入输出中(作为 的:
RHS 上的左操作数,=
产生式规则的右侧部分),并other
通过递归调用检查列表 ( )的其余部分(右侧该 RHS 的操作数:
);otherwise
这个四元组被跳过,只考虑剩下的部分。
最后一行中的匹配处理任何少于四个元素的列表(这可能是文件的结尾)。由于我们不太可能在如此短的列表中找到更多导演的电影,我们只需返回[]
。
因此,例如,如果我们有一个列表
["Blade Runner", "Ridley Scott", "1982", " ", "Alien", "Ridley Scott", "1979", " "]
然后寻找斯科特的电影,我们得到:
首先, list 与(title:director:year:_:others)
. 然后绑定变量:title
是“银翼杀手”,director
是“雷德利斯科特”,year
是“1982”,others
是["Alien", "Ridley Scott", "1979", " "]
. 由于director
等于我们正在寻找的名称,我们采用第一条路径并宣布["Blade Runner", "Ridley Scott", "1982"]:moviesBy "Ridley Scott" ["Alien", "Ridley Scott", "1979", " "]
为我们的结果。
接下来,递归调用以构造结果列表的尾部。这里再次title
是“Alien”,director
“Ridley Scott”,year
是“1979”并且others
绑定到一个空列表。因此,步骤 1. 的结果列表的尾部是["Alien", "Ridley Scott", "1979"]:moviesBy "Ridley Scott" []
。
最后一次递归调用。我们不能将至少四个元素模式绑定到空列表,因此我们采用最后一个选项,moviesBy _ _
匹配字符串和列表的任意组合,这里的结果是 [](递归停止)。因此,步骤 2. 的结果是["Alien", "Ridley Scott", "1979"]:[]
,换句话说,[["Alien", "Ridley Scott", "1979"]]
。并且在 1. 中添加 head ,该函数的总结果是[["Blade Runner", "Ridley Scott", "1982"], ["Alien", "Ridley Scott", "1979"]]
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句