Конкретный тип Пример функтора, который не может быть аппликативным?

Из функторов, которые не являются применимыми:

Конструктор типа, который является функтором, но не аппликативным. Простым примером является пара:

instance Functor ((,) r) where
    fmap f (x,y) = (x, f y)

Но нет способа определить свой экземпляр Applicative, не налагая дополнительных ограничений на r. В частности, нет способа определить pure :: a -> (r, a) для произвольного r.

Здесь pure не может быть определен для всех типов одновременно; однако для любого бетонного типа T можно сделать ((,) T) аппликативным.

Вопрос: Есть ли пример конкретного функтора (т.е. не имеющих переменных типа), который является функтором, но не аппликативным?

Ответ 1

У меня нет 50 репутации, чтобы комментировать здесь, поэтому я постараюсь сделать это как ответ:

однако для любого конкретного типа T можно сделать ((,) T) аппликативным.

...

В математике есть теорема о том, что любая коллекция с не менее чем двумя элементами может быть превращена в моноид. Таким образом, для любого конкретного типа T он мог бы в принципе быть членом Моноида, а затем в принципе можно было бы сделать аппликативным. Что не так с этим рассуждением?

Как насчет кортежа из необитаемого типа? (,) Void

Это Functor, правильно?

Вы можете получить Applicative для него? Как реализовать pure?

Ответ 2

Есть хороший пример в реактивно-банановая библиотека.

Он содержит типы Event a, которые представляют одно одновременное событие во времени (думаю, импульс) и Behavior a, которое представляет значение, доступное в любой момент (например, испускающее значение из последнее событие).

Поведение является аппликативным, потому что вы можете объединить два из них - они имеют значение в любой момент времени.

введите описание изображения здесь

Событие, однако, является только Functor, потому что вы не можете объединить их. Учитывая два Event, вы не можете быть уверены, что они будут выполняться одновременно.

Событие

Ответ 3

"[Тем не менее], для любого конкретного типа T можно сделать ((,) T) аппликативным" - на самом деле. Вам все еще нужно T быть моноидом, а не только из-за чистого: вам также нужно реализовать (<*>) таким образом, чтобы эти два метода соответствовали применимым законам.

[...]

В математике есть теорема о том, что любая коллекция с не менее чем двумя элементами может быть превращена в моноид. Таким образом, для любого конкретного типа T его можно было бы в принципе сделать членом Monoid, а затем в принципе можно было бы сделать Applicative. Что не так с этим рассуждением?

"В принципе" необязательно переводится в код. Рассмотрим:

newtype UserID = UserID Integer

Насколько я могу судить, для UserID нет значимого экземпляра Monoid. В принципе, можно использовать 0 и (+) в базовом Integer, но это будет означать утечку детали реализации без уважительной причины (и, скорее всего, ее можно скрыть, сделав абстрактный тип). Таким образом, (,) UserID был бы прекрасным примером a Functor, который не является Applicative.