This question already has an answer here:
-
Good examples of Not a Functor/Functor/Applicative/Monad?
5 answers
From functors that are not applicatives:
A type constructor which is a Functor but not an Applicative. A simple example is a pair:
instance Functor ((,) r) where
fmap f (x,y) = (x, f y)
But there is no way how to define its Applicative
instance without imposing additional restrictions on r
. In particular, there is no way how to define pure :: a -> (r, a)
for an arbitrary r
.
Here, pure
fails to be definable for all types at once; however, for any concrete type T
, one can make ((,) T)
an applicative.
Question: Is there an example of a concrete functor (i.e., no type variables involved) that is a functor but not an applicative?
I don't have 50 reputation to comment here, so I'll try to do it as an answer:
however, for any concrete type T, one can make ((,) T) an applicative.
...
There's a theorem in mathematics that any collection with at least 2 elements can be made into a monoid. So for any concrete type T, it could in principle be made a member of Monoid, and then could in principle be made Applicative. What's wrong with this reasoning?
What about the tuple from the uninhabited type? (,) Void
It is a Functor
,right?
Could you derive Applicative
for it? How would pure
be implemented?
There is nice example in reactive-banana library.
It features Event a
types, which represents a single simultaneous event in time (think, an impulse), and Behavior a
type, which represents a value that is available in any moment (for instance, emitting a value from the last event).
Behavior is an Applicative, because you can combine two of them - they have a value in any point of time.
Event, though, is a Functor only, because you can't combine them. Given two Event
s you can't be sure they will happen simultaneosly.
"[However], for any concrete type T
, one can make ((,) T)
an applicative" -- not really. You still need T
to be a monoid, and not just because of pure: you also need to implement (<*>)
in a way that the two methods follow the applicative laws.
[...]
There's a theorem in mathematics that any collection with at least 2 elements can be made into a monoid. So for any concrete type T
, it could in principle be made a member of Monoid
, and then could in principle be made Applicative
. What's wrong with this reasoning?
The "in principle" doesn't necessarily translate into code. Consider:
newtype UserID = UserID Integer
As far as I can see, there is no meaningful Monoid
instance for UserID
. In principle, one might use 0
and (+)
on the underlying Integer
, but that would amount to leaking an implementation detail for no good reason (and which is likely end up being hidden by making the type abstract). That being so, (,) UserID
would be a perfectly good example of a Functor
which is not an Applicative
.