Ответ 1
В этом вопросе есть по крайней мере три важных аспекта.
-
Учитывая экземпляр
Monad m
, какова спецификация его необходимого экземпляра суперклассаApplicative m
? Ответ:pure
-return
,<*>
-ap
, поэтомуmf <*> ms == do f <- mf; s <- ms; return (f s)
Обратите внимание, что эта спецификация не является законом класса Applicative
. Это требование на Monad
s, чтобы обеспечить согласованные шаблоны использования.
-
Учитывая, что спецификация (по реализации кандидата), является
ap
единственной приемлемой реализацией. Ответ: громко, нет. Зависимость значений, разрешенная типом>>=
, может иногда приводить к неэффективному выполнению: бывают ситуации, когда<*>
можно сделать более эффективным, чемap
, потому что вам не нужно ждать завершения первого вычисления до вас может сказать, что такое второе вычисление. Для того, чтобы использовать эту возможность, существует "апликативная" запись. -
Выполняют ли какие-либо другие экземпляры-кандидаты для
Applicative
законыApplicative
, даже если они не согласны с требуемыми экземплярамиap
? Ответ: да. "Обратный" пример, предложенный вопросом, - это просто вещь. В самом деле, как замечает другой ответ, любое приложение может быть повернуто назад, и результат часто является другим зверем.
В следующем примере и упражнении для читателя обратите внимание, что непустые списки являются монадическими в обычном порядке из обычных списков.
data Nellist x = x :& Maybe (Nellist x)
necat :: Nellist x -> Nellist x -> Nellist x
necat (x :& Nothing) ys = x :& Just ys
necat (x :& Just xs) ys = x :& Just (necat xs ys)
instance Monad Nellist where
return x = x :& Nothing
(x :& Nothing) >>= k = k x
(x :& Just xs) >>= k = necat (k x) (xs >>= k)
Найдите по крайней мере четыре различных по-разному экземпляра Applicative Nellist
, которые подчиняются прикладным законам.