• монады Haskell Пусть у нас есть очень полиморфный concatMap :: (a -> c b) -> c a -> c b где c — какой-то класс контейнеров. Как с минимальными ограничениями для класса c получить concatMapM :: Monad m => (a -> m (c b)) -> c a -> m (c b)?

Replies (9)

  • @ndtimofeev, Чтобы m (c a) превратить в c (m a) для использование контейнерного concatMap нужна функция m (c a) -> c (m a). Похоже сама монада должна быть Traversable, а c, например, Applicative.
  • @yantayga, Пардон?
  • @ndtimofeev, Если c — монадный трансформер, то сразу все хорошо. А вот более слабых ограничений я пока придумать не могу.
  • @lomeo, Стоп. Для обходительных контейнеров есть mapM :: Monad m => (a -> m b) -> c a -> m (c b). С другой стороны a -> m b запросто может оказаться a -> m (c t). На выходе мы получим m (c (c t)), что легко превращается в m (c t) если c — монада. По моему «Задача решена, ура! Землекопа полтора!». Поправьте меня, если я не прав.
  • @balodja, Меня бы устроила монада. А как через трансформер?
  • @ndtimofeev, Ну, если c — трансформер, что c m — монада. И concatMapM — это немного видоизмененный (=<<), конкретнее concatMapM f x = f =<< (return x).
  • @ndtimofeev, Можно и так, в моём случае c меньше, чем монада, зато m больше чем монада. Ты спрашивал про минимальные ограничения для класса c.
  • @lomeo, Это я выдал желаемое за действительное. По причине того что вся эта дребедень — часть трансформера, в который m приходит «снизу» — это именно Monad и ничего кроме. Для меня это было настолько очевидно, что я забыл об этом упомянуть. Кроме того, я тут внезапно сообразил, что ситуация, когда получается что-то вроде c (m a) крайне нежелательна. Контейнеры не редко накладывают свои ограничения на хранимые значения и для m они могут оказаться несколько обременительны.