Понимание примера на Writer Monad

Я узнаю о писательской монаде по книге "Learn You A Haskell".

это кусок кода:

import Control.Monad.Writer

logNumber :: Int -> Writer [String] Int
logNumber num = writer (num, ["Got number: " ++ show num])

multWithLog :: Writer [String] Int
multWithLog = do
  a <- logNumber 3
  b <- logNumber 5
  return (a * b)

При беге multWithLog, это результат:

*Main> runWriter multWithLog
(15,["Got number: 3","Got number: 5"])

На этой строчке:

a <- logNumber 3
b <- logNumber 5

Легко видеть, что a = 3 а также b = 5так как они оба умножаются на return функция.

Я не понимаю, почему эти ценности 3 а также 5, не должны a а также b быть значения, которые содержат внутри Writer Монада? В этом случае кортежи?

Например, с этим было с Maybe Монада, a а также bбыло бы 3 а также 5:

do
  a <- Just 3
  b <- Just 5
  return (a * b)

В этом случае это имеет смысл для меня, так как a а также b получить контент внутри Just, Но с первоначальным примером, a а также b только получить часть стоимости.

3 ответа

Решение

Легко видеть, что a = 3 и b = 5, так как они оба умножаются на функцию возврата. Я не понимаю, почему эти значения равны 3 и 5. Разве a и b не должны быть значениями, содержащимися в монаде Writer? В этом случае кортежи?

Нет. Я думаю, что самый простой способ ответить на это - просто реализовать Writer набери и изучи его Monad экземпляр класса:

newtype Writer w a = Writer { runWriter :: (a, w) }

instance Functor (Writer w) where
  fmap f (Writer (a, w)) = Writer (f a, w)

instance Monoid w => Applicative (Writer w) where
  pure a = Writer (a, mempty)
  Writer (f, w) <*> Writer (a, w') = Writer (f a, w <> w')

instance Monoid w => Monad (Writer w) where
  return = pure
  Writer (a, w) >>= f = let (b, w') = runWriter (f a)
                        in Writer (b, w <> w')

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

Как вы можете видеть в методе экземпляра для >>=, функция f применяется к a значение, а не весь кортеж. Синтаксис a <- logNumber 3 desugared с помощью >>=так что значение, которое связано с a будет первым элементом кортежа, который Writer оборачивается.

В этом случае это имеет смысл для меня, так как a а также b получить контент внутри Just, Но с первоначальным примером, a а также b только получить часть стоимости.

В этом описании нет ничего плохого, но мы также можем взглянуть на эту ситуацию по-другому. В...

  a <- Just 3

... мы могли бы также сказать, что a получает только часть Just 3 - Just обертка не делает это. С этой точки зрения, что происходит с...

  a <- writer (3, ["Got number: " ++ show 3])

... в достаточной степени похож: a только получает 3 значение. [String] аннотации, так сказать, остаются на заднем плане, получая mappendсоединены друг с другом монадическими связями, очень похоже на (>>=) комбинаты Maybeтак что Just с Just дает Just а также Nothing с чем-нибудь дает Nothing,

Идея "значений, содержащихся в монаде" немного размыта. Это отчасти работает, но не строго.

Действительно, монада как таковая не содержит ничего. Знаете, это не скафандр или буррито...

В случае WriterВы можете четко сказать, что это тип, значения которого содержат как log-snippets, так и результаты вычислений. Последнее - это то, что вы можете интерпретировать как "содержание" монады, и то, что вы можете получить с помощью a <-, Но в целом такого контента вообще не должно быть.

На самом деле, чтобы остаться с вашим Maybe пример:

do a <- Just 3
   Nothing
   b <- Just 5
   return (a * b)

В этом случае Nothing "Прерывает" вычисление, поэтому Just 5 никогда не вводить значение 5 в a,

Имейте в виду, что если action :: M T для какой-то монады M, затем

do
   ...
   a <- action

может дать a значение типа T, (В вашем примере M является Writer [String] а также T является Int, так a может иметь только тип Int.)

Будет ли это на самом деле, как часто, откуда приходят значения и что это означает, зависит от конкретной монады. Тем не менее, законы монады могут многое рассказать о том, как будут вести себя все вычисления. Но, изучая монады, вероятно, лучше всего забыть обо всем этом, просто взглянуть на множество различных примеров и побаловать себя монадами самостоятельно, в какой-то момент вы получите для них интуицию. Не пытайтесь "понять" монады по аналогиям.

Другие вопросы по тегам