Haskell IO Bool Сложите вопрос - PullRequest
       26

Haskell IO Bool Сложите вопрос

1 голос
/ 12 декабря 2010

Как я могу написать функцию, которая выполняет функции логики и функции между элементами списка?

Я написал это:

iand :: [IO Bool] -> IO Bool

iand [] = return (True)
iand (x:xs) = do
  a <- x 
  b <- iand(xs)
  return (a && b)

Но это кажется бессознательным.

Как переписать эту функцию с помощью foldM (liftM)?

Спасибо.

Ответы [ 3 ]

10 голосов
/ 12 декабря 2010

Функция Prelude and :: [Bool] -> Bool почти делает то, что вы хотите, но она не монадическая.Вообще говоря, чтобы поднять функцию с одним аргументом в монаду, вам понадобится Control.Monad's liftM :: Monad m => (a -> b) -> m a -> b a;однако, чтобы быть более общим, вы можете использовать Prelude в fmap :: Functor f => (a -> b) -> f a -> f b.Все монады являются функторами 1 , так что все в порядке.Таким образом, вы можете использовать

fand' :: Functor f => f [Bool] -> f Bool
fand' = fmap and

Однако, по крайней мере, в 90% случаев я бы просто записал это значение как fmap and xs, или, более вероятно, and <$> xs, используя Control.Applicative's <$> синоним fmap.

Конечно, как я уверен, вы заметили, это не то, что вы хотите.Для этого вам понадобится прелюдия 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 's'«лучше», в некотором смысле это налагает дополнительное ограничение Functor m.То, что не должно быть проблемой, но это может быть по историческим причинам, поэтому я проигнорировал.

Кроме того, вы можете спросить: «Как бы я узнал о sequence«?Ответ на этот вопрос - замечательный Hoogle , который позволяет вам искать функции Haskell по имени или типу .Итак, поскольку вы знали о liftM :: Monad m => (a -> b) -> m a -> m b, вы могли бы понять, что вам нужно что-то вроде Monad m => [m a] -> m [a];Смеяться над этим действительно получается sequence.


1: Или, по крайней мере, так должно быть - по историческим причинам, хотя этоне всегда так.

2 голосов
/ 12 декабря 2010

Вы можете использовать liftM, чтобы превратить and (который имеет тип [Bool] -> Bool) в функцию типа IO [Bool] -> IO Bool и sequence, чтобы превратить ваш [IO Bool] в IO [Bool].

Итак, ваша функция становится:

iand ibs = liftM and (sequence ibs)
1 голос
/ 12 декабря 2010

Разве это не будет iand list = foldl (&&) True list?

...