如何在Haskell中的类文件系统结构中进行搜索

时间:2014-12-08 17:41:45

标签: file haskell search

问题

我有一个类型:

data FSObject = Folder String [FSObject] | File String

我需要创建一个函数

search :: String -> FSObject -> Maybe String

返回我们正在搜索的文件的路径(如果存在) (搜索函数中的字符串应该等于搜索文件的名称(File对象中的字符串(无路径))。

我的想法/尝试

我觉得我没有以正常的方式做到这一点。我是这门语言的新手,所以我很抱歉以下代码。

我试图这样做几个小时。我这样想:

heler function contains如果给定的FSObject包含我们正在寻找的文件

,则返回true

使用File返回第一个元素的辅助函数(使用上一个函数和"查找"函数)

帮助函数处理从Maybe String到String的转换

我的搜索功能会检查是否有文件,如果没有 - >;返回Nothing,否则返回Just with String以某种方式使用递归计算

我可以粘贴我的作品,但我不知道如何使它工作,它完全不可读等。

some1是否有提示/评论要分享?如何在这类问题中正确处理Maybe?

3 个答案:

答案 0 :(得分:1)

您可以使用递归来完成此操作。

findPath::String->FSObject->Maybe String
findPath name (File name') | name == name' = Just name
findPath _ (File _) = Nothing
findPath name (Folder path contents) = 
             fmap ((path ++ "/") ++) $ msum $ map (findPath name) contents 

唯一棘手的问题是最后一部分。打破最后一行......

map (findPath name) contents

将输出子结果列表

[Just "a/b/filename", Nothing, Just "c/d/filename", ....]

msum将取出第一个Just在列表中,将其余部分抛弃(并且,通过懒惰,实际上不会创建第一个值)

最后,路径前置(fmap可以到达Maybe内)

答案 1 :(得分:1)

虽然@jamshidh解决方案很短,但它不是模块化的,而是最终的结果。这是我编写程序的过程。两个要点:

  • 我将使用所谓的“生成然后搜索”方法:首先我为所有文件生成路径,然后我在集合中搜索正确的路径
  • 我将路径存储为组件列表 - 这样代码将更通用(在Haskell中更通用的代码更不容易出错)并且我将在一个小函数中插入路径分隔符(所以我可以做一个在一个更容易的事情。)

好的我需要函数allPaths,它给出了所有文件的列表及其路径。单个文件的所有路径都是单个文件,文件夹的所有路径都是来自具有前置文件夹名称的子项的路径的串联集合:

allPaths (File file) = singleFile file
allPaths (Folder folder children) = concatMap (addFolder folder . allPaths) children

我实际上是自上而下编写的代码。所以此时我没有费心去定义singleFileaddFolder。单个文件很简单:

singleFile file = [(file, [])]

addFolderf添加到元组的第二个组件。 Control.Arrow已经有了一个函数,但为了简单起见,我在这里添加了它的实现:

second f (a,x) = (a, f x)

addFolder f files = map (second (f:)) files

当我学习Haskell时,很难立刻编写这样的代码,但现在它是自动的,没有中间步骤。

现在我们基本上通过过滤所有匹配的文件来实现search,进行第一次匹配并提取路径。哦,标准库中已有函数lookup

search fileToSearch l = lookup fileToSearch $ allPaths l

我花了很长时间才弄清楚如何撰写lookupallPaths。幸运的是,元组中的顺序是偶然选择的。

请注意,您仍然需要通过插入分隔符并根据需要使用concatMap附加文件名将文件夹列表转换为路径。

答案 2 :(得分:0)

您应该使用累积参数创建一个递归函数,以将当前路径保存在搜索中。会是这样的:

    search str (File f) = if str == f then Just str else Nothing
    search str (Directory dir (x:xs)) = 
       Just (sear str [] (Directory dir (x:xs))) where
            sear str path (File f) = if str == f then (path ++ "/" ++ str ++ "|") else []
            sear str path (Directory y []) = []
            sear str path (Directory dir (x:xs)) = sear str (path ++ "/" ++ dir) x ++ sear str path (Directory dir xs)

希望对您有所帮助。