монадные преобразователи и стекирование нескольких монад
-
22-09-2019 - |
Вопрос
у меня есть функция f
с подписью f :: [a] -> StateT Int Reader b [c]
, и f'
с подписью f' :: a -> StateT Int Reader b [c]
Вычисление в f (очень упрощенное) выглядит так:
f [] = return []
f (s:st) = f' s >>= \x ->
f st >>= \y ->
return $ ...
И вместо...Я хотел бы вернуть [c]
часть x
++
тот [c]
часть y
с обернутыми вокруг монадами.
Есть ли возможность добиться этого без развертывания вручную? x
и y
и снова вручную собрать результат?Нужна ли мне монада List в нижней части стека монад, чтобы получить простой код?Монада Reader, очевидно, не является экземпляром класса MonadPlus.
Решение
Я не понимаю, что вы имеете в виду под разворачиванием x
и y
.
У меня была бы последняя строка как
return (x ++ y)
Я неправильно понимаю, чего вы хотите?
Другие советы
Вы также можете просто определить
f = fmap concat . mapM f'
(mapM f' xs
выдает значение типа m [[c]]
, где xs :: [a]
и m = StateT Int (Reader b)
, а потом fmap concat
объединяет списки «внутри монады».)
Оба f' s
и f st
являются значениями в одной монаде, а именно StateT Int Reader b
.Итак, у вас уже есть x :: [c]
и y :: [c]
и вам просто нужно написать return (x ++ y)
, как сказал Дэйв Хинтон.