Учитывая действие
foo :: Int -> WriterLS Bool
foo x
| x >= 0 = tell "poz" >> return True
| otherwise = tell "neg" >> return False
, вы можете сделать runWriter (Writer (1, []) >>= foo)
, чтобы получить (True,["poz"])
. Но выглядит приятнее сказать runWriter (return 1 >>= foo)
, поскольку вы превратили return
в вспомогательную функцию, которая абстрагирует подробности о записанном списке.
Следующим шагом может быть написание действия
foos :: [Int] -> WriterLS [Bool]
foos [] = pure []
foos (x:xs) = do
b <- foo x
bs <- foos xs
return (b:bs)
где вы можете сделать runWriter (pure [1,-2,3] >>= foos)
и получить
([True,False,True],["poz","neg","poz"])
Тогда вы достигли своего результата более конкретным способом, но вы не обобщили рекурсивную часть foos
в некоторые Карта как функция, как вы хотите. Я думаю, что это легче, если вы знакомы с происходящей рекурсией.
Как намекает Виллем, когда вы говорите «карта», вы, вероятно, захотите взглянуть на fmap
, так как WriterLS
- это Functor
, что является математическим способом сказать, что он сопоставим в том смысле, к которому вы стремитесь. И, как подсказывает Чепнер, если вы откроете GHCi и наберете :t fmap foo
, вы получите:
λ> :t fmap foo
fmap foo :: Functor f => f Int -> f (WriterLS Bool)
fmap foo :: [Int] -> [WriterLS Bool] -- when f = []
, что довольно близко, но не совсем так же, как [Int] -> WriterLS [Bool]
. Затем вы могли бы спросить у Google о чем-то, что напоминает недостающую часть, Monad m => [m a] -> m [a]
.