Подтвердить что ты не робот

Может ли лифтМ отличать от liftA?

Согласно Typeclassopedia (среди прочих источников), Applicative логически принадлежит между Monad и Pointed (и, следовательно, Functor) в иерархии классов типов, поэтому в идеале у нас было бы что-то подобное, если бы прелюдия Haskell была написана сегодня:

class Functor f where
    fmap :: (a -> b) -> f a -> f b

class Functor f => Pointed f where
    pure :: a -> f a

class Pointed f => Applicative f where
    (<*>) :: f (a -> b) -> f a -> f b

class Applicative m => Monad m where
    -- either the traditional bind operation
    (>>=) :: (m a) -> (a -> m b) -> m b
    -- or the join operation, which together with fmap is enough
    join :: m (m a) -> m a
    -- or both with mutual default definitions
    f >>= x = join ((fmap f) x)
    join x = x >>= id
    -- with return replaced by the inherited pure
    -- ignoring fail for the purposes of discussion

(Если эти определения по умолчанию были повторно введены мной из описания в Википедии, ошибки были моими собственными, но если есть ошибки, по крайней мере, в принципе возможно.)

Поскольку библиотеки в настоящее время определены, мы имеем:

liftA :: (Applicative f) => (a -> b) -> f a -> f b
liftM ::       (Monad m) => (a -> b) -> m a -> m b

и

(<*>) :: (Applicative f) => f (a -> b) -> f a -> f b
ap    ::       (Monad m) => m (a -> b) -> m a -> m b

Обратите внимание на сходство между этими типами в каждой паре.

Мой вопрос: are liftM (в отличие от liftA) и ap (в отличие от <*>), просто результат исторической реальности, что Monad не был разработан с Pointed и Applicative в виду? Или они по каким-то другим поведенческим образом (потенциально, для некоторых легальных определений Monad) отличаются от версий, для которых требуется только контекст Applicative?

Если они различны, можете ли вы предоставить простой набор определений (подчиняясь законам, требуемым для Monad, Applicative, Pointed и Functor определений, описанных в Typeclassopedia и в других местах, но не выполняемых типа), для которых liftA и liftM ведут себя по-другому?

Альтернативно, если они не отличаются друг от друга, можете ли вы доказать их эквивалентность с использованием тех же законов, что и помещения?

4b9b3361

Ответ 1

liftA, liftM, fmap и . должны быть одинаковой функцией, и они должны быть, если они удовлетворяют закону функтора:

fmap id = id

Однако это не проверяется Haskell.

Теперь для аппликативного. Для <функторов > ap и <*> возможно различать некоторые функторы просто потому, что может быть более одной реализации, которая удовлетворяет типам и законам. Например, List имеет более одного возможного экземпляра Applicative. Вы можете объявить применение следующим образом:

instance Applicative [] where
  (f:fs) <*> (x:xs) = f x : fs <*> xs
  _      <*> _      = []
  pure              = repeat

Функция ap по-прежнему будет определена как liftM2 id, которая является экземпляром Applicative, который поставляется бесплатно с каждым Monad. Но здесь у вас есть пример конструктора типа, имеющего более одного экземпляра Applicative, оба из которых удовлетворяют законам. Но если ваши монады и ваши аппликативные функции не согласны, они считают, что хорошая форма имеет для них разные типы. Например, приведенный выше пример Applicative не согласуется с монадой для [], поэтому вы должны действительно сказать newtype ZipList a = ZipList [a], а затем создать новый экземпляр для ZipList вместо [].

Ответ 2

Они могут отличаться, но они не должны.

Они могут различаться, потому что они могут иметь разные реализации: один определяется в instance Applicative, а другой - в instance Monad. Но если они действительно отличаются, то я бы сказал, что программист, который написал эти экземпляры, написал вводящий в заблуждение код.

Вы правы: функции существуют так же, как и по историческим причинам. У людей есть сильные идеи о том, как должно было быть.