我是Haskell的新手,我试图映射检查文件是否存在的检查函数,如下所示:
check :: FilePath -> IO Bool
来自Main的argv,如下:
main :: IO Bool
main = do {
args <- getArgs;
return $ foldM (&&) True $ mapM check args;
}
基本上逻辑是,将IO [Bool]的数组折叠成单个IO Bool并返回它。我使用Monadic版本的Map and Fold,因为我带着IO monad,但是我从类型检查器中得到了很多错误,我无法解释因为引入了占位符,我对此一无所知。
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;
|
有关如何让typechecker满意的任何线索?
答案 0 :(得分:5)
foldM
的类型是:
GHCi> :t foldM
foldM
:: (Monad m, Foldable t) => (b -> a -> m b) -> b -> t a -> m b
你给它的二元函数应该在一些monad m
中产生monadic结果(在你的情况下,m
将是IO
)。但是,(&&)
不会产生monadic结果。这意味着你在这里不需要foldM
:普通折叠会:
GHCi> :t foldr (&&) True
foldr (&&) True :: Foldable t => t Bool -> Bool
顺便提一下,foldr (&&) True
在Prelude中以and
的形式提供,因此您只需使用它即可。要将and
应用于[Bool]
中的IO
列表,您可以使用fmap
。然后你的do-block的最后一行变成:
fmap and $ mapM check args
或者,使用(<$>)
,即fmap
的中缀拼写:
and <$> mapM check args
(正如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
(return ()
在这里只是一个无所事事的占位符。)
使用来自when
的{{1}}的更好的表达方式:
Control.Monad
答案 1 :(得分:1)
不确定这是否是唯一的错误,但foldM
来电的结果已经是IO Bool
;不需要return
它。这只会将它包装在另一层monad中。