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

Почему в Haskell нет класса "Cofunctor"?

Монады получают fmap из Functor typeclass. Почему comonads не нужен метод cofmap, определенный в классе Cofunctor?

4b9b3361

Ответ 1

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

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

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)

Ответ 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 — not a.