Каждая монада - аппликативный функтор - обобщающий на другие категории - PullRequest
0 голосов
/ 27 декабря 2018

Я могу с готовностью определить общие Functor и Monad классы в Haskell:

class (Category s, Category t) => Functor s t f where
    map :: s a b -> t (f a) (f b)

class Functor s s m => Monad s m where
    pure :: s a (m a)
    join :: s (m (m a)) (m a)
    join = bind id
    bind :: s a (m b) -> s (m a) (m b)
    bind f = join . map f

Я читаю этот пост , который объясняет, что аппликативный функтор является слабым (закрытый или моноидальный) функтор.Это происходит в терминах (экспоненциального или моноидального) бифунктора.Я знаю, что в категории Haskell каждый Monad равен Applicative;как мы можем обобщить?Как мы должны выбрать (экспоненциальный или моноидальный) функтор, в терминах которого можно определить Applicative?Что меня смущает, так это то, что наш Monad класс, похоже, не имеет никакого представления о (закрытой или моноидальной) структуре.

Редактировать: Комментатор говорит, что это вообще невозможно, поэтому теперь часть моего вопроса заключается в том, где онвозможно.

Ответы [ 2 ]

0 голосов
/ 27 декабря 2018

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

class (Category s, Category t) => Functor s t f where
  map :: s a b -> t (f a) (f b)

class Functor s t f => Monoidal s t f where
  pureUnit :: t () (f ())
  fzip :: t (f a,f b) (f (a,b))

s -морфизмов, только если вы рассмотрите законы моноидального функтора, которые примерно говорят, что моноидальная структура s должен быть отображен в эту моноидальную структуру t с помощью функтора.

Возможно, более проницательным является включение fmap в методы класса, поэтому ясно, что "func -" - частьФунктор делает:

class Functor s t f => Monoidal s t f where
  ...
  puref :: s () y -> t () (f y)
  puref f = map f . pureUnit
  fzipWith :: s (a,b) c -> t (f a,f b) (f c)
  fzipWith f = map f . fzip

С Monoidal мы можем вернуть нашего старого доброго Hask - Applicative таким образом:

pure :: Monoidal (->) (->) f => a -> f a
pure a = puref (const a) ()

(<*>) :: Monoidal (->) (->) f => f (a->b) -> f a -> f b
fs <*> xs = fzipWith (uncurry ($)) (fs, xs)

или

liftA2 :: Monoidal (->) (->) f => (a->b->c) -> f a -> f b -> f c
liftA2 f xs ys = fzipWith (uncurry f) (xs,ys)

Возможно, более интересным в этом контексте является другое направление, потому что оно показывает нам связь с монадами в обобщенном случае:

instance Applicative f => Monoidal (->) (->) f where
  pureUnit = pure
  fzip = \(xs,ys) -> liftA2 (,) xs ys
       = \(xs,ys) -> join $ map (\x -> map (x,) ys) xs

То, что секции лямбды и кортежей недоступны вобщая категория, однако они могут быть переведены в декартовы закрытые категории .


Я использую (,) в качестве продукта вобе моноидальные категории, с единичным элементом ().В более общем случае вы можете написать data I_s и data I_t и type family (⊗) x y и type family (∙) x y для продуктов и соответствующих им элементов идентификации.

0 голосов
/ 27 декабря 2018

Что меня смущает, так это то, что наш класс Монад, кажется, не имеет никакого представления о (закрытой или моноидальной) структуре.

Если бы я правильно понял ваш вопрос, это было бы обеспечено через тензорную силу монады.Класс Monad не имеет его, потому что он присущ категории Hask .Конкретнее, предполагается:

t :: Monad m => (a, m b) -> m (a,b)
t (x, my) = my >>= \y -> return (x,y) 
...