Конкретный тип Пример функтора, который не может быть аппликативным?
Из функторов, которые не являются применимыми:
Конструктор типа, который является функтором, но не аппликативным. Простым примером является пара:
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
.