Почему в Haskell существуют две разные монады типа Writer? Интуитивно для меня, чтение "строгой монады писателя" означает, что <>
является строгим, так что в журнале не создается нарастание громкости. Однако, глядя на исходный код, выясняется, что это не так:
-- Lazy Writer
instance (Monoid w, Monad m) => Monad (WriterT w m) where
-- ...
m >>= k = WriterT $ do
~(a, w) <- runWriterT m
~(b, w') <- runWriterT (k a)
return (b, w <> w')
В строгой версии шаблоны не являются неопровержимыми, т.е. отсутствуют теги ~
. Итак, что происходит выше, это то, что m
и k a
не оцениваются, а сохраняются как thunks. В строгой версии они оцениваются, чтобы проверить, соответствуют ли они шаблонам кортежа, результат подается на <>
. В обоих случаях параметр >>=
не оценивается до тех пор, пока что-то фактически не потребует результирующего значения.
Таким образом, я понимаю, что и ленивые, и строгие версии делают то же самое, за исключением того, что у них есть thunk в другом месте внутри определения >>=
: lazy производит runWriterT
thunks, strict производит <>
thunks.
Это оставляет мне два вопроса:
- Правильно ли это, или я неправильно понимаю оценку здесь?
- Можно ли выполнить строгую
<>
без написания моей собственной оболочки и экземпляра?