2016-01-11 2 views
11

Monads получает fmap от Functor typeclass. Почему comonads не нужен метод cofmap, определенный в классе Cofunctor?Почему в Haskell нет класса «Кофейник»?

+4

Это потому, что кофунктор такое же, как функтор. Между ними нет никакой разницы. Однако монады и комонады разные. Существует такая вещь, как контравариантный функтор, но с методом «contramap», который имеет тип «контравариант f => (a -> b) -> f b -> f a'. Однако это не то же самое, что кофейник. –

+0

Вы имеете в виду «cofunctor» как двойственный функтор (который является просто функтором, поскольку он является самодвойственным) или означает контракторный функтор? http://math.stackexchange.com/questions/394472/is-cofunctor-an-accepted-term-for-contravariant-functors –

ответ

19

Functor определяется как:

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

Cofunctor может быть определена следующим образом:

class Cofunctor f where 
    cofmap :: (b -> a) -> (f b -> f a) 

Таким образом, оба технически же, и именно поэтому Cofunctor не существует. «Двойное понятие« функтора вообще »по-прежнему является« функтором вообще »».

С Functor и Cofunctor такие же, как монады, так и комонады определяются с помощью Functor. Но не позволяйте этому заставлять вас думать, что монады и комонады - это одно и то же, а это не так.

Монадой определяется (упрощение), как:

class Functor m => Monad where 
    return :: a -> m a 
    (>>=) :: m a -> (a -> m b) -> m b 

является ли комонадой (опять же, упрощенный):

class Functor w => Comonad where 
    extract :: w a -> a 
    extend :: (w a -> b) -> w a -> w b 

Обратите внимание на "симметрии".


Другое дело контравариантный функтор, определяемый как:

import Data.Functor.Contravariant 
class Contravariant f where 
    contramap :: (b -> a) -> (f a -> f b) 
+6

Не было бы двойственным функтором C -> D функтором D -> C? Таким образом, двойственный функтор ** ** является не тем же самым функтором, но двойственное понятие «функтора вообще» по-прежнему является «функтором вообще». Я думаю, что я просто играю семантику, но язык в «функторе - это сам двойной» звучит как утверждение о том, что индивидуальный функтор каким-то образом можно использовать как свой собственный обратный или что-то еще. – Ben

+0

@Ben Вы правы. Я исправил это. –

+0

@Ben Это более или менее соответствует формальному определению: https://en.wikipedia.org/wiki/Equivalence_of_categories#Definition – Zaaier

3

Для справки,

class Functor w => Comonad w where 
    extract :: w a -> a 
    duplicate :: w a -> w (w a) 
    extend :: (w a -> b) -> w a -> w b 

instance Applicative m => Monad m where 
    return :: a -> m a 
    (>>=) :: m a -> (a -> m b) -> m b 

join :: Monad m => m (m a) -> m a 

Обратите внимание, что данный extract и extend вы можете производить fmap и duplicate, и что, учитывая return и >>= вы можете произвести fmap, pure, <*> и join. Поэтому мы можем сосредоточиться только на pure + >>= и extract + extend.

Я полагаю, вы могли бы искать что-то вроде

class InverseFunctor f where 
    unmap :: (f a -> f b) -> a -> b 

Поскольку Monad класс позволяет легко «навести» в то время как только позволяет некий гипотетический подход к «принимая вещи», и Comonad что-то противное, ваш запрос изначально звучит разумно. Тем не менее, существует значительная асимметрия между >>= и extend, которая будет мешать любой попытке определить unmap. Обратите внимание, в частности, что первый аргумент >>= имеет тип m a. Второй аргумент extend имеет тип w aнеa.

+0

мы могли бы определить unmap с помощью: «unmap f = extract. F. Return» и подписи типа "unmap :: Monad f, Comonad f => (fa -> fb) -> a -> b" – Stratege

Смежные вопросы