Typeclassopedia представляет Traversable:Traversable # mapM & sequence - Обязательно?
class (Functor t, Foldable t) => Traversable t where
traverse :: Applicative f => (a -> f b) -> t a -> f (t b)
sequenceA :: Applicative f => t (f a) -> f (t a)
mapM :: Monad m => (a -> m b) -> t a -> m (t b)
sequence :: Monad m => t (m a) -> m (t a)
Хорошее упражнение, чтобы выяснить, что реализация по умолчанию должно быть: Дано либо траверс или sequenceA, как бы вы определили три другие методы?
я придумал следующий код, который тип провер:
class (Functor t, Foldable t) => MyTraversable t where
traverse' :: Applicative f => (a -> f b) -> t a -> f (t b)
traverse' = error "..."
sequenceA' :: Applicative f => t (f a) -> f (t a)
sequenceA' f = traverse' id f
mapM :: Monad m => (a -> m b) -> t a -> m (t b)
mapM = traverse'
sequence' :: Monad m => t (m a) -> m (t a)
sequence' = sequenceA'
Если мои реализации mapM
и sequence'
являются правильными, и, поскольку каждая Монада является Аппликативной:
λ: :i Monad
class Applicative m => Monad (m :: * -> *) where
...
, тогда мне непонятно, почему нужны mapM
и sequence'
. Почему они?
P.S. - Кредит и моя благодарность haoformayor за то, что помогли мне с sequenceA
.
Было неловкое время, когда не каждая «Монада» была «аппликативной». –
Вы не спрашивали об этом, но вы должны * никогда * не создавать метод класса по умолчанию, который всегда вызывает ошибку. Просто не делайте дефолт в этом случае; GHC будет предупреждать, если метод не определен в экземпляре. С ложным значением по умолчанию пользователи не получают никаких предупреждений; вещи просто взрываются во время работы. – dfeuer