Функция Prelude and :: [Bool] -> Bool
почти делает то, что вы хотите, но это не монадическая. Вообще говоря, чтобы поднять функцию одного аргумента в монаду, вам понадобится Control.Monad's liftM :: Monad m => (a -> b) -> m a -> b a
; однако, чтобы быть более общим, вы можете использовать Prelude's fmap :: Functor f => (a -> b) -> f a -> f b
. Все монады являются функторами , так что это нормально. Таким образом, вы можете использовать
fand' :: Functor f => f [Bool] -> f Bool
fand' = fmap and
Однако, по крайней мере, 90% времени, я бы просто написать, что встроенный в fmap and xs
, или более вероятно and <$> xs
, используя <$>
синоним Control.Applicative для fmap
.
Конечно, я уверен, что вы заметили, что это не то, что вы хотите. Для этого вам нужен Prelude sequence :: Monad m => [m a] -> m [a]
. Теперь у вас есть функция [m a] -> m [a]
и функция f [Bool] -> f Bool
, так что мы можем объединить эти:
mand :: Monad m => [m Bool] -> m Bool
mand = liftM and . sequence
я перешел на liftM
из fmap
, потому что, хотя fmap
«ы„лучше“в каком-то смысле, это было бы наложить дополнительные Functor m
ограничение. То, что не должно быть, может быть проблемой, но это может быть по историческим причинам, поэтому я играл в нее безопасно.
Кроме того, вы можете спросить: «Как бы я узнал о sequence
»? Ответ на этот вопрос - замечательный Hoogle, который позволяет вам искать функции Haskell по названию или типа. Итак, поскольку вы знали о liftM :: Monad m => (a -> b) -> m a -> m b
, возможно, вы поняли, что вам нужно что-то вроде Monad m => [m a] -> m [a]
; Hoogling для этого does indeed turn up sequence
.
1: Или, по крайней мере, они должны быть, по историческим причинам, однако, это не всегда так.
Спасибо!Но он говорит: «Не удалось сопоставить ожидаемый тип' m »с предполагаемым типом' [] '' для функции mand. В чем проблема? – 4DA
@Dmitry: Ой, это потому, что я опечатал. Я утверждал, что 'mand :: Monad m => m [Bool] -> m Bool', что, очевидно, глупо, так как * point * этого упражнения состояла в том, чтобы построить вам функцию с типом' Monad m => [m Bool ] -> m Bool'. Если вы исправите это утверждение типа, все будет работать. Я отредактировал свой ответ соответственно. –