I’m trying to understand the applicative typeclass, and in particular the <*> function. Now I see its type signature is f (a -> b) -> f a -> f b and I take it that f is a functor, which I think of as some kind of structure wrapping some data. It appears to me that f must handle generic types, specifically it must be possible for f to have the parameterized types a, b, and in fact it must also support a -> b.
If my understanding is correct, then what we are doing is working with a typeclass f that is initially intended to wrap some data, like say a list of strings or a tree containing file buffers or whatever random thing we might want. But f must not be committed to any one type, because not only must it handle such a type but it is also required to handle functions from the data to the other data. Thus if we had an example implementation of <*> which contained
Just2 f <*> j = fmap f j
the way to read this is that j is some kind of data inside of a Just2. f is a function which maps data to data. And f is wrapped in a Just2.
Is all of that right? Fundamentally my question is: Must anything applicative be so generic that it can always simultaneously handle arbitrary data and also functions from data to data? Or is there some way that you could have an applicative such that the only data it allows inside is, say, lists?