• ? code Haskell category
    Народ, а ведь по категорным законам вот такое должно всегда выполняться для инстансов Applicative и Monad одного типа?
    ```
    let x = (,) <$> a <*> b
    let y = do 
        aa <- a 
        bb <- b
        return (aa, bb)
    x == b
    ```

Replies (22)

  • @PineappleZombie, Так и думал, значит мой аппликатив не может быть монадой. Вообще, интересно, что любой инстанс Applicative можно делать непрерывающимся, даже Maybe например(все зависит от закладываемого в ADT смысла). А вот монада обязана обрываться, если чистое значение взять не откуда.
  • @PineappleZombie, а `<-` вместо `let`?
  • @qnikst, Нуу, нет, эффекты тоже должны быть одинаковые, понятно что IO ты не сравнишь например.
  • @segfault, ты в посте сравниваешь.. Ничего не понимаю
  • @qnikst, Я не IO сравниваю, а некий произвольный тип. Если там будет '<-' вместо 'let', то до сравнения вычисление может и не добраться.
  • @qnikst, Я вообще не вижу причин, почему они обязаны быть одинаковыми.. Но я не помню категорных законов.
  • @qnikst, <*> можно реализовать в терминах >>= и return. И оно должно вести себя именно так, еси я правильно помню
  • @qnikst, Потому что монада — это аппликатив, который можно плющить, вроде как.
  • @PineappleZombie, Да ну, вот для IO я могу сделать аппликатив, который forkIO каждого действия делает и собирает результат. В итоге результат тот же, но действие разное. Тоже самое для Builder, который для немонадического действа модифицируется.
  • @qnikst, Можешь, но это будет не правильно, просто хаскель тебе по рукам не ударит. По нормальному, для такого надо заводить newtype, как минимум.
  • @qnikst, Но, по моему, результат и все наблюдаемые эффекты должны быть одинаковы. <*> ≡ ap

    С другой стороны для Applicative можно заниматься оптимизациями вроде параллелизации и т.д.
  • @segfault, Из того, что монада это аппликатив, не для меня не следует что действие будет тем же, т.к. для апликатива ты знаешь, что параллельные действия не связаны, в результате возможно использования этого знания. А вот дефолтная реализация вполне может совпадать. P.S. это без учёта законов, которые могут сказать мне что я не прав.
  • @qnikst, параллельные действия не связаныКак это не связаны?
    ```
    (,) <$> [1,2,3] <*> [4,5,6]
    ```
    тут тоже ?
  • @PineappleZombie, Согласен, но при этом действие порождающее эффекты и результат может отличаться
  • @qnikst, С чисто практической точки зрения, если эффекты в монадическом и аппликативном интерфейсе разные — это сколь угодно большой источник багов
  • @segfault, Связывает действие bind, для аппликейтива bind нету, в результате у тебя структура проще и возможны оптимизаци, которые невозможны в monad. Говоря что действие такое же или тв понимаешь это в терминах эффектов и результата или это не так.
  • @qnikst, Оптимизации! Наблюдаемое поведение то же, но реализовано более эффективно. Т.е. замена монад на applicative не изменит смысла программы, но может сделать её более быстрой
  • @PineappleZombie, что не отменяет `x == y'
  • @segfault, подразумевает
  • @segfault, 1. (,) <$> a <*> b

    2. liftM2 id (fmap (,) a) b

    3. (fmap (,) a) >>= \x -> b >>= \bb -> return (id x bb)

    4. a >>= (return . (,)) >>= \x -> b >>= \bb -> return (x bb)

    5. a >>= \aa -> (return . (,) $ aa) >>= \x -> b >>= \bb -> return (x bb)

    6. a >>= \aa -> return (aa,) >>= \x -> b >>= \bb -> return (x bb)

    7. a >>= \aa -> b >>= \bb -> return ((aa,) bb)

    8. a >>= \aa -> b >>= \bb -> return (aa, bb)

    1-2: Выражение <$> и <*> через монадные методы. 2-3: Определение для liftM2. 3-4: Выражение для fmap через return и bind. 4-5: Ассоциативный закон для монады. 5-6: Раскрытие $. 6-7: Левая единица монады. 7-8: La grande finale.

    Короче не смог.