Haskell 了解filterM函数

Haskell 了解filterM函数,haskell,functional-programming,Haskell,Functional Programming,我正在学习Miran Lipovaca的《为伟大的事业学习Haskell》一书中的filterM功能。对于以下示例: keepSmall :: Int -> Writer [String] Bool keepSmall x | x < 4 = do tell ["Keeping " ++ show x] return True | otherwise = do tell [show x ++ " is too large, thro

我正在学习Miran Lipovaca的《为伟大的事业学习Haskell》一书中的
filterM
功能。对于以下示例:

keepSmall :: Int -> Writer [String] Bool
keepSmall x
   | x < 4 = do
       tell ["Keeping " ++ show x]
       return True
   | otherwise = do
      tell [show x ++ " is too large, throwing it away"]
      return False
关于
filterM
的结果类型,我知道
filterM
具有以下类型声明:

filterM :: (Monad m) => (a -> m Bool) -> [a] -> m [a]

由于本例中使用的monad是
Writer[String]
,因此
filterM
产生的列表类型是否为
Writer[String][Int]
?如果是这种情况,这就是为什么结果类型是
([Int],[String])
,因为
Writer wa
相当于元组
(a,w)

这是因为
runWriter

runWriter :: Writer w a -> (a, w)
从Hoogle,它实际上只是将writer计算作为(结果、输出)对展开。这就是为什么你得到了一对的结果

举个小例子,看看它在其他环境中是如何工作的:

runWriter (tell $ return "Hello" ())
=> ((),"Hello")
返回“Hello”(=“Hello”
因为
实例Monad((->)a)其中{return=const;…}
runWriter (tell $ return "Hello" ())
=> ((),"Hello")