Haskell如何运作`tell` work

时间:2017-08-16 05:59:09

标签: haskell

我正在学习do expressionMonad使用了解你是一个非常好的HASKELL 。使用gcd函数的tell实现让我感到困惑。

gcd :: Int -> Int -> Writer [String] Int
gcd a b
  | b == 0 = tell ["Finished with " ++ show a ] >>= (\_ -> return a)
  | otherwise = tell [show a ++ " mod " ++ show b ++ " = " ++ show (a `mod` b)] >>= (\_ -> gcd b (a `mod` b))

gcdResult = gcd 8 3

-- result: WriterT (Identity (1,["8 mod 3 = 2","3 mod 2 = 1","2 mod 1 = 0","Finished with 1"]))

但我对tell函数感到困惑。使用>>= (\_ -> ...)>>时,之前的结果将被忽略,那么为什么tell的结果可以传递给最终结果?根据我的想法,tell结果可能会被忽略,最终结果将是WriterT (Identity (1,[]))

1 个答案:

答案 0 :(得分:12)

您将结果与上下文混淆。您是正确的,在应用>>>>= \_ ->时,会忽略左侧的结果。但是,如果忽略整个价值,那将是完全没有意义的; monadic环境可以向前传递。

a >> b

这意味着“从a获取上下文并将其与b的上下文相结合,保持结果值为b”。在Writer的情况下,monadic上下文是传递了一些只写数据。

tell :: Monoid w => w -> Writer w ()

这是tell的(略微简化)类型。它需要一个值来编写并返回一个Writer实例,其结果值无关紧要(()),但其上下文是包含w参数的只写值。当您应用>>时,结果值将被忽略(这是无关紧要的,因为tell在结果中没有返回任何值),但保留了上下文