Какова цель контрамапа?



Я прочитал много статей о контрамапе и нашел https://hackage.haskell.org/package/contravariant-1.4.1/docs/Data-Functor-Contravariant.html#g:3- это самое лучшее.



В любом случае я нашел, как использовать, например:



*Lib Data.Functor.Contravariant> a = Predicate (x -> x > 20)
*Lib Data.Functor.Contravariant> :t contramap
contramap :: Contravariant f => (a -> b) -> f b -> f a
*Lib Data.Functor.Contravariant> :t contramap (x -> x * 2)
contramap (x -> x * 2) :: (Num b, Contravariant f) => f b -> f b
*Lib Data.Functor.Contravariant> :t contramap (x -> x * 2) a
contramap (x -> x * 2) a :: (Ord b, Num b) => Predicate b
*Lib Data.Functor.Contravariant> x = contramap (x -> x * 2) a
*Lib Data.Functor.Contravariant> getPredicate x 45
True


Но никак не мог сообразить, где это может пригодиться.

На веб-сайте, который я разместил выше, написано:




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




Посмотрите на определение функтора:



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


Он потребляет значение типа a и производит значение типа b. На contramap он потребляет значение.

class Contravariant (f :: * -> *) where
contramap :: (a -> b) -> f b -> f a


Какой тип переменной он использует a или b?



Также вопрос от https://www.fpcomplete.com/blog/2016/11/covariance-contravariance о положительной и отрицательной позиции . На сайте говорит:




  • положительная позиция: переменная типа является
    результат / выход / диапазон / кодомен функции

  • отрицательная позиция: переменная типа является аргументом / входом / областью
    функция


Глядя на определение типа contramap:



contramap :: (a -> b) -> f b -> f a


На какую переменную типа указывает автор?

584   2  

2 ответов:

Считается, что функтор f "содержит" или "производит" значения в том смысле, что f a подобен контейнеру a значений. fmap позволяет преобразовать значения, содержащиеся в f.
Примеры:

  • [a] 'содержит' неотрицательное число значений типа a
  • IO a потенциально делает некоторый IO и "возвращает" или "производит" значение типа a
  • (->) r a 'содержит' значение типа a для каждого значения r

Теперь a Contravariant f это то, что может "принимать" или "потреблять" ценности. contramap позволяет преобразовать вещь f a, Прежде чем она их поглотит.
Главным примером для этого обычно является использование чего-то вроде
newtype Op r a = Op { runOp :: a -> r }
(обратите внимание, что Predicate, который вы использовали, кажется, просто Op Bool)
Теперь у нас есть нечто, что может "потреблять" значения типа А. (аналогия может иметь больше смысла для Op (IO ()))
Продолжая этот пример "потребления" ценностей, рассмотрим o = Op (\x -> putStrLn x) :: Op (IO ()) String, теперь что, если мы хотим использовать o, но для значений типа Show a => a? Ну вот для чего нужен contramap!
contramap show o :: Show a => Op (IO ()) a
(обратите внимание, что в этом простом случае runOp (contramap show o) просто print)

Правка:
Еще одна интересная вещь, которую следует отметить о Contravariant, касается ее составления.
Дано Contravariant c, Contravariant d, Functor f и
newtype Compose f g a = Compose { runCompose :: f (g a) }
у нас есть:

  • Compose f c также Contravariant
    contramap f (Compose fca) = Compose $ fmap (contramap f) fca
  • Compose c f также Contravariant
    contramap f (Compose cfa) = Compose $ contramap (fmap f) cfa
  • Compose c d на самом деле является Functor
    fmap f (Compose cda) = Compose $ contramap (contramap f) cda

Посмотрите на определение функтора:

class Functor (f :: * -> *) where
    fmap :: (a -> b) -> f a -> f b
Он потребляет значение типа a и производит значение типа b.
Это не совсем точно и является источником вашего замешательства. В частности, существуют три различных объекта в типе fmap: функция a -> b, "функциональное" значение f a и" функциональное " значение f b, и то, потребляется ли a или производится, зависит от этих объектов, так же как и то, является ли b потребляется или производится.
  • функция типа a -> b потребляет и a и производит b. (Это предложение, которое вы сказали, но с новым добавлением, указывающим , к какому объекту оно применяется.)
  • Если f является Functor, то значение типа f a "производит" as.
  • Если f является Functor, то значение типа f b "производит" bs.
Мы можем распространить эти наблюдения на более крупные типы функций.
  • Если f является Functor, тогда функция типа f a -> f b потребляет f as и производит f b s; и поскольку функторы положительны, это в свою очередь означает, что функция потребляет a s и производит b s.
  • Если f является Functor, то функция типа (a -> b) -> f a -> f b потребляет a -> b - то есть в реализации мы будем производить a s, чтобы обеспечить функцию a -> b и потреблять b s, которые она возвращает! Он делает это, чтобы произвести f a -> f b, который потребляет as и производит b s.

N. B. роль" потреблять "и" производить "чередуется довольно много в приведенном выше описании, даже в пределах одного объекта, который называется fmap; так сказать," fmap потребляет as и производит bs " не говорит всей истории.

Аналогично неточна и следующая формулировка:

В то время как в Хаскелле можно думать о Functor как о содержании или производстве значений, контравариантный функтор-это функтор, который можно рассматривать как потребляющий ценности.

Вы интерпретировали это так, что fmap как объект (функция) содержит значения, в то время как contramap производит значения. Но это не то, что было задумано; вместо этого, утверждение должно было быть о самих (контравариантных) функториальных значениях, а не о (контра)отображениях, которые применяются к ним. Более точным утверждением является следующее:

В то время как в Хаскелле можно думать о значении типа f a (для которого f является Functor) Как содержащем или производя значения a, контравариантный функтор f порождает значения типа f a, которые можно рассматривать как потребляющие значения a.

Что касается вашего вопроса о положительных и отрицательных позициях, вы можете насладиться некоторыми из моих предыдущих обсуждений этой темы здесь на SO.

Comments

    Ничего не найдено.