我是Haskell的新手,我正在尝试映射检查文件是否存在的检查函数,如下所示:
check :: FilePath -> IO Bool
来自Main的argv,如下:
main :: IO Bool
main = do {
args <- getArgs;
return $ foldM (&&) True $ mapM check args;
}
Run Code Online (Sandbox Code Playgroud)
基本上逻辑是,将IO [Bool]的数组折叠成单个IO Bool并返回它.我使用地图的单子版本和折叠,因为我身边携带IO单子,但我得到了很多来自typechecker,我不能因为占位符真正破译错误的介绍,我什么都不知道关于.
src/Main.hs:15:9: error:
• Couldn't match type ‘m0 Bool’ with ‘Bool’
Expected type: IO Bool
Actual type: IO (m0 Bool)
• In a stmt of a 'do' block:
return $ foldM (&&) True $ mapM check args
In the expression:
do args <- getArgs
return $ foldM (&&) True $ mapM check args
In an equation for ‘main’:
main
= do args <- getArgs
return $ foldM (&&) True $ mapM check args
|
15 | return $ foldM (&&) True $ mapM check args;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/Main.hs:15:24: error:
• Couldn't match type ‘Bool’ with ‘m0 Bool’
Expected type: Bool -> Bool -> m0 Bool
Actual type: Bool -> Bool -> Bool
• In the first argument of ‘foldM’, namely ‘(&&)’
In the expression: foldM (&&) True
In the second argument of ‘($)’, namely
‘foldM (&&) True $ mapM check args’
|
15 | return $ foldM (&&) True $ mapM check args;
| ^^^^
src/Main.hs:15:36: error:
• Couldn't match type ‘[Bool]’ with ‘Bool’
Expected type: IO Bool
Actual type: IO [Bool]
• In the second argument of ‘($)’, namely ‘mapM check args’
In the second argument of ‘($)’, namely
‘foldM (&&) True $ mapM check args’
In a stmt of a 'do' block:
return $ foldM (&&) True $ mapM check args
|
15 | return $ foldM (&&) True $ mapM check args;
|
Run Code Online (Sandbox Code Playgroud)
任何线索如何让typechecker开心?
类型foldM是:
GHCi> :t foldM
foldM
:: (Monad m, Foldable t) => (b -> a -> m b) -> b -> t a -> m b
Run Code Online (Sandbox Code Playgroud)
你给它的二进制函数应该在一些monad中产生monadic结果m(在你的情况下,m将是IO).(&&)但是,不产生一元结果.这意味着你不需要foldM这里:普通折叠会做:
GHCi> :t foldr (&&) True
foldr (&&) True :: Foldable t => t Bool -> Bool
Run Code Online (Sandbox Code Playgroud)
顺便提一下,foldr (&&) True在Prelude中and可以使用,因此您可以使用它.要申请and加入您的[Bool]清单IO,您可以使用fmap.你的do-block的最后一行然后变成:
fmap and $ mapM check args
Run Code Online (Sandbox Code Playgroud)
或者,使用(<$>),这是中缀拼写fmap:
and <$> mapM check args
Run Code Online (Sandbox Code Playgroud)
(正如Sebastian Redl所指出的那样,这return是不必要的,因为已经and <$> mapM check args是类型IO Bool了.)
顺便说一下,请注意,给出main类型IO Bool不会达到预期效果 - 返回值将main被丢弃.要返回错误退出代码,您可以使用,例如exitFailure:
argsOK <- and <$> mapM check args
if not argsOK
then exitFailure
else return ()
-- rest of your do-block
Run Code Online (Sandbox Code Playgroud)
(return ()这里只是一个无所事事的占位符.)
该表达的更好的方法是使用when从Control.Monad:
argsOK <- and <$> mapM check args
when (not argsOK) exitFailure
-- rest of your do-block
Run Code Online (Sandbox Code Playgroud)