Is it possible to write a function for generic types (in this case applicatives) without making assumptions about the name of type constructors?
I can write the following:
f :: Maybe a -> Maybe a
f (Just a) = (Just a)
That one works on Maybe
s and only instances with the Just
constructor.
But say I had different types that have a value constructor that had the same name as the type constructor:
data T a = T a
instance Functor T where
fmap f (T a) = T (f a)
instance Applicative T where
pure = T
(T f) <*> (T something) = fmap f (T something)
data U a = U a
instance Functor U where
fmap f (U a) = U (f a)
instance Applicative U where
pure = U
(U f) <*> (U something) = fmap f (U something)
In this case T
and U
are isomorphic, but maybe they also would have constructors that are special to either one in a real example... does not matter here.
Now what if wanted a function that operates both on T
and U
... I could write the function two times, like so:
gt :: T a -> T a
gt (T x) = T x
gu :: U a -> U a
gu (U x) = U x
Is there also a way to make a template for this function like this?
g :: (Applicative f) => f a -> f a
g (f x) = f x
That will give me a syntax error for some reason, even though it has the same structure as gt
and gu
.
If there is no way to do that then why not?