在 IO monad 中获取列表的第一个元素
Getting a first element of the list within IO monad
我正在尝试从 IO monad 链中获取第一个元素(据我了解,我仍在学习 Haskell):
getSomePath :: FilePath -> IO [FilePath]
getSomePath path = do
pomFile <- listDirectory path >>= filterM (\x -> return $ x == "pom.xml") >>= head
-- here I'll add some more files
return [pomFile, someOtherFile]
当我尝试应用 head
函数时出现错误:
Couldn't match type ‘[Char]’ with ‘IO FilePath’
Expected type: [[Char]] -> IO FilePath
Actual type: [IO FilePath] -> IO FilePath
• In the second argument of ‘(>>=)’, namely ‘head’
In a stmt of a 'do' block:
pomFile <- listDirectory path
>>= filterM (\ x -> return $ x == "pom.xml")
>>= head
我也试过:
pomFile <- head (listDirectory path >>= filterM (\x -> return $ x == "pom.xml"))
没有结果。我应该如何将 head 函数应用于 IO [a]
类型以使其结果为 IO a
?是否有 head
等效于将其应用于 monad?我知道我可以只使用 System.Directory.findFile 或类似的东西,但我想了解为什么我的方法不起作用。
您不能使用 head
,因为这里的参数是 IO [a]
,而不是 a
。但是,您可以在此基础上 fmap :: Function f => (a -> b) -> f a -> f b
,从而获得 IO a
,或使用运算符别名 <$>
.
也就是说,这里使用filterM
不需要,您可以只过滤列表,然后取头部:
pomFile <- (head . filter ("pom.xml" ==)) <b><$></b> listDirectory path
然而以上内容并不安全。如果目录确实包含 "pom.xml"
,那么它将简单地 return 一个 FilePath
(String
) 即 "pom.xml"
。如果不是,它会引发一个错误,表明您的目标是检索空列表的头部。
因此您可能只需要使用:
hasPomFile <- elem "pom.xml" <$> listDirectory path
这里 hasPomFile
是 Bool
,如果目录包含 "pom.xml"
,则 True
,否则 False
。
我正在尝试从 IO monad 链中获取第一个元素(据我了解,我仍在学习 Haskell):
getSomePath :: FilePath -> IO [FilePath]
getSomePath path = do
pomFile <- listDirectory path >>= filterM (\x -> return $ x == "pom.xml") >>= head
-- here I'll add some more files
return [pomFile, someOtherFile]
当我尝试应用 head
函数时出现错误:
Couldn't match type ‘[Char]’ with ‘IO FilePath’
Expected type: [[Char]] -> IO FilePath
Actual type: [IO FilePath] -> IO FilePath
• In the second argument of ‘(>>=)’, namely ‘head’
In a stmt of a 'do' block:
pomFile <- listDirectory path
>>= filterM (\ x -> return $ x == "pom.xml")
>>= head
我也试过:
pomFile <- head (listDirectory path >>= filterM (\x -> return $ x == "pom.xml"))
没有结果。我应该如何将 head 函数应用于 IO [a]
类型以使其结果为 IO a
?是否有 head
等效于将其应用于 monad?我知道我可以只使用 System.Directory.findFile 或类似的东西,但我想了解为什么我的方法不起作用。
您不能使用 head
,因为这里的参数是 IO [a]
,而不是 a
。但是,您可以在此基础上 fmap :: Function f => (a -> b) -> f a -> f b
,从而获得 IO a
,或使用运算符别名 <$>
.
也就是说,这里使用filterM
不需要,您可以只过滤列表,然后取头部:
pomFile <- (head . filter ("pom.xml" ==)) <b><$></b> listDirectory path
然而以上内容并不安全。如果目录确实包含 "pom.xml"
,那么它将简单地 return 一个 FilePath
(String
) 即 "pom.xml"
。如果不是,它会引发一个错误,表明您的目标是检索空列表的头部。
因此您可能只需要使用:
hasPomFile <- elem "pom.xml" <$> listDirectory path
这里 hasPomFile
是 Bool
,如果目录包含 "pom.xml"
,则 True
,否则 False
。