I'm learning do expression
and Monad
using LEARN YOU A HASKELL FOR GREAT GOOD . There's a gcd
implementation using tell
function makes me confused.
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"]))
But I am confused by the tell
function. When using >>= (\\_ -> ...)
or >>
, the result before will be ignored, so why does the result of tell
can be passed to the final result? As my thought, the tell
result may be ignored, and the final result will be WriterT (Identity (1,[]))
.
You're confusing the result with the context. You are correct that, when applying >>
or >>= \\_ ->
, the result of the left-hand-side is ignored. However, if the entire value was ignored, it would be completely pointless; the monadic context can be passed forward.
a >> b
This means "take the context from a
and combine it with the context of b
, keeping the result value of b
". In the case of Writer
, the monadic context is that there is some write-only data being passed about.
tell :: Monoid w => w -> Writer w ()
This is the (somewhat simplified) type of tell
. It takes a value to write and returns a Writer
instance whose result value is insignificant ( ()
) but whose context is that there is a write-only value containing the w
argument. When you apply >>
, the result value is ignored (which is irrelevant because tell
returns nothing of value through its result) but the context is kept.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.