正在对 'do' 个块进行脱糖

Desugaring 'do' blocks

我在翻译这条 do 声明时遇到了一些问题:

ex10 :: [Int]
ex10 = do
    num <- [1..20]
    guard (even num)
    guard (num `mod` 3 == 0)
    return num

变成某种 monad 语法,如下所示:

ex10' :: [Int]
ex10' = [1..20] >>= (guard . even) >>= (guard . (==0) . (mod 3)) >>= \r -> return r

这不起作用,我不太清楚为什么。我想我可能误解了 guard 但我不确定是什么意思。

guard 的类型是 MonadPlus m => Bool -> m () 所以你的第三个片段

(guard . (==0) . (mod 3))

收到类型为 () 的值,这不是您想要的。在 do 符号中

do
  guard (even num)
  guard (num `mod` 3 == 0)

被脱糖成类似

的东西
guard (even num) >> guard (num `mod` 3 == 0)

所以您可以将 ex10' 实现为

 ex10' = [1..20] >>= (\num -> (guard $ even num) >> (guard $ num `mod` 3 == 0) >> return num)