问题
我有一个类型:
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?
答案 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解决方案很短,但它不是模块化的,而是最终的结果。这是我编写程序的过程。两个要点:
好的我需要函数allPaths,它给出了所有文件的列表及其路径。单个文件的所有路径都是单个文件,文件夹的所有路径都是来自具有前置文件夹名称的子项的路径的串联集合:
allPaths (File file) = singleFile file
allPaths (Folder folder children) = concatMap (addFolder folder . allPaths) children
我实际上是自上而下编写的代码。所以此时我没有费心去定义singleFile
和addFolder
。单个文件很简单:
singleFile file = [(file, [])]
addFolder
将f
添加到元组的第二个组件。 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
我花了很长时间才弄清楚如何撰写lookup
和allPaths
。幸运的是,元组中的顺序是偶然选择的。
请注意,您仍然需要通过插入分隔符并根据需要使用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)
希望对您有所帮助。