刚开始学习哈斯克尔 - 一周后爱上它。目前正在经历monads的痛苦,但目前还没有,但希望它会点击。
我正在尝试将类似于pythons walk()的函数放在一起但更简单。 给定一个路径,我想生成元组列表。每个子目录的元组(假设只有目录)。元组将包含目录的路径作为其第一个元素,目录包含的文件列表作为第二个元素。
我不知道我是否正确解释了它,但这是代码:
walkDir :: String -> IO [IO (FilePath, [FilePath])]
walkDir path = do
dir <- getDirectoryContents path
let nd = [x | x <- dir, notElem x [".",".."]]
return (map getcont nd)
where
getcont path = do
cont <- getDirectoryContents path
return (path,cont)
我关心的是IO里面的IO以及如何处理它?可以取消它们吗? 是否可以至少打开内部IO?这种回归是否正常?
我甚至无法打印这种回报。我是否必须创建一个show实例才能正确打印?
在某些haskell库中很可能存在类似的功能,但这是出于教育目的。我想学习。所以欢迎任何建议。
非常感谢。
答案 0 :(得分:10)
答案 1 :(得分:4)
让我们来看看类型。
map :: (a -> b) -> [a] -> [b]
getCont :: FilePath -> IO (FilePath, [FilePath])
nd :: [FilePath]
map getCont nd :: [IO (FilePath, FilePath)]
现在,在这一点上,结构从内向外看。我们有[IO a]
,但我们需要IO [a]
。停止!霍格时间。推广任何ol'monad,我们都会[m a] -> m [a]。瞧,sequence
有这种精确的类型签名。因此,您应使用return :: a -> m a
而不是sequence :: [m a] -> m [a]
,而不是sequence (map getCont nd)
:
mapM f xs = sequence (map f xs)
然后你就会全力以赴。请注意,这与Kurt S的解决方案基本相同,因为
{{1}}