Multiple arguments on applicatives not working? - haskell

So I'm trying to learn about monads, functors and applicatives. I've created the following renamed mirror match of Maybe called Sometimes. (I did this to learn about these things)
data Sometimes a = Nope | Thing a deriving Show
instance Monad Sometimes where
(Thing x) >>= f = f x
Nope >>= f = Nope
return = Thing
instance Applicative Sometimes where
pure = Thing
Nope <*> _ = Nope
(Thing g) <*> mx = fmap g mx
instance Functor Sometimes where
fmap _ Nope = Nope
fmap g (Thing x) = Thing (g x)
So when I do the following it works:
pure (1+) <*> (Thing 1)
> Thing 2
pure (+) <*> (Thing 1) <*> (Thing 1)
> Thing 2
But if I try three additions it doesn't work:
pure (+) <*> (Thing 1) <*> (pure 1) <*> (pure 1)
<interactive>:108:1: error:
• Non type-variable argument in the constraint: Num (a -> b)
(Use FlexibleContexts to permit this)
• When checking the inferred type
it :: forall a b. (Num (a -> b), Num a) => Sometimes b
Why doesn't this work? I would expect the first two to be applied and then the third to be applied to the result of the first two. My book talks about how implementing fmap0, fmap1, fmap2... is inefficient and as such
... for functions with any desired number of arguments can be constructed in terms of two basic functions with the following types:
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
And states further on:
A typical use of pure and <*> has the following form:
pure g <*> x1 <*> x2 <*> ... <*> xn
As such I'm expecting it to work but I'm clearly missing something in my definitions/usage of the Applicative.
I'm using the book Programming in Haskell SE by Graham Hutton

The reason this does not work is because (+) sums two numbers, not three.
You can make a function that sums three numbers, for example with:
pure (\x y z -> x+y+z) <*> (Thing 1) <*> (pure 1) <*> (pure 1)
this then gives us:
Prelude> pure (\x y z -> x+y+z) <*> (Thing 1) <*> (pure 1) <*> (pure 1)
Thing 3
Why doesn't this work? I would expect the first two to be applied and then the third to be applied to the result of the first two.
Exactly, but after the first two are applied, this is no longer a function, but a Num a => Sometimes a. Indeed, if we determines the types, we see that Thing (+) :: Num a => Sometimes (a -> a -> a) and Thing 1 :: Num b => Sometimes b, so that means that Thing (+) <*> Thing 1 has type Num a => Sometimes (a -> a).
Then we determine the type of Thing (+) <*> Thing 1 <*> Thing 1, since Thing (+) <*> Thing 1 has type Num a => Sometimes (a -> a), and the last Thing 1 has type Num c => Sometimes c, it means that Thing (+) <*> Thing 1 <*> Thing 1 has type Num a => Sometimes a, but this is not a function, unless there is a Num type that is a function, which is what the error is saying.

Related

Understanding Functions as Applicatives in Haskell

I've recently been trying to learn Haskell with the "Learn You a Haskell" and have been really struggling with understanding functions as Applicatives. I should point out that using other types of Applicatives like Lists and Maybe I seem to understand well enough to use them effectively.
As I tend to do when trying to understand something is I tried to play with as many examples as I could and once the pattern emerges things tend to make sense. As such I tried a few examples. Attached are my notes of several examples I tried along with a diagram I drew to try to visualize what was happening.
The definition of funct doesnt seem to relevant to the outcome but in my tests I used a function with the following definition:
funct :: (Num a) => a -> a -> a -> a
At the bottom I tried to show the same thing as in the diagrams just using normal math notation.
So all of this is well and good, I can understand the pattern when I have some function of an arbitrary number of arguments (though needs 2 or more) and apply it to a function that takes one argument. However intuitively this pattern doesn't make that much sense to me.
So here are the specific questions I have:
What is the intuitive way to understand the pattern I'm seeing, particularly if i view an Applicative as a container (which is how I view Maybe and lists)?
What is the pattern when the function on the right of the <*> takes more than a single argument (I've mostly been using the function (+3) or (+5) on the right)?
why is the function on the right hand side of the <*> applied to the second argument of the function on the left side. For example if the function on the right hand side were f() then funct(a,b,c) turns into funct (x, f(x), c)?
Why does it work for funct <*> (+3) but not for funct <*> (+)? Moreover it DOES work for (\ a b -> 3) <*> (+)
Any explanation that gives me a better intuitive understanding for this concept would be greatly appreciated. I read other explanations such as in the book I mentioned that explains functions in terms of ((->)r) or similar patterns but even though I know how to use the ->) operator when defining a function I'm not sure i understand it in this context.
Extra Details:
I want to also include the actual code I used to help me form the diagrams above.
First I defined funct as I showed above with:
funct :: (Num a) => a -> a -> a -> a
Throughout the process i refined funct in various ways to understand what was going on.
Next I tried this code:
funct a b c = 6
functMod = funct <*> (+3)
functMod 2 3
Unsuprisingly the result was 6
So now I tried just returning each argument directly like this:
funct a b c = a
functMod = funct <*> (+3)
functMod 2 3 -- returns 2
funct a b c = b
functMod = funct <*> (+3)
functMod 2 3 -- returns 5
funct a b c = c
functMod = funct <*> (+3)
functMod 2 3 -- returns 3
From this I was able to confirm the second diagram is what was taking place. I repeated this patterns to observe the third diagram as well (which is the same patterns extended on top a second time).
You can usually understand what a function is doing in Haskell if you
substitute its definition into some examples. You already have some
examples and the definition you need is <*> for (->) a which is
this:
(f <*> g) x = f x (g x)
I don't know if you'll find any better intuition than just using the
definition a few times.
On your first example we get this:
(funct <*> (+3)) x
= funct x ((+3) x)
= funct x (x+3)
(Since there was nothing I could do with funct <*> (+3) without a
further parameter I just applied it to x - do this any time you need
to.)
And the rest:
(funct <*> (+3) <*> (+5)) x
= (funct x (x+3) <*> (+5)) x
= funct x (x+3) x ((+5) x)
= funct x (x+3) x (x+5)
(funct <*> (+)) x
= funct x ((+) x)
= funct x (x+)
Notice you can't use the same funct with both of these - in
the first it can take four numbers, but in the second it needs to take
a number and a function.
((\a b -> 3) <*> (+)) x
= (\a b -> 3) x (x+)
= (\b -> 3) (x+)
= 3
(((\a b -> a + b) <*> (+)) x
= (\a b -> a + b) x (x+)
= x + (x+)
= type error
As pointed out by David Fletcher, (<*>) for functions is:
(g <*> f) x = g x (f x)
There are two intuitive pictures of (<*>) for functions which, though not quite able to stop it from being dizzying, might help with keeping your balance as you go through code that uses it. In the next few paragraphs, I will use (+) <*> negate as a running example, so you might want to try it out a few times in GHCi before continuing.
The first picture is (<*>) as applying the result of a function to the result of another function:
g <*> f = \x -> (g x) (f x)
For instance, (+) <*> negate passes an argument to both (+) and negate, giving out a function and a number respectively, and then applies one to the other...
(+) <*> negate = \x -> (x +) (negate x)
... which explains why its result is always 0.
The second picture is (<*>) as a variation on function composition in which the argument is also used to determine what the second function to be composed will be
g <*> f = \x -> (g x . f) x
From that point of view, (+) <*> negate negates the argument and then adds the argument to the result:
(+) <*> negate = \x -> ((x +) . negate) x
If you have a funct :: Num a => a -> a -> a -> a, funct <*> (+3) works because:
In terms of the first picture: (+ 3) x is a number, and so you can apply funct x to it, ending up with funct x ((+ 3) x), a function that takes two arguments.
In terms of the second picture: funct x is a function (of type Num a => a -> a -> a) that takes a number, and so you can compose it with (+ 3) :: Num a => a -> a.
On the other hand, with funct <*> (+), we have:
In terms of the first picture: (+) x is not a number, but a Num a => a -> a function, and so you can't apply funct x to it.
In terms of the second picture: the result type of (+), when seen as a function of one argument ((+) :: Num a => a -> (a -> a)), is Num a => a -> a (and not Num a => a), and so you can't compose it with funct x (which expects a Num a => a).
For an arbitrary example of something that does work with (+) as the second argument to (<*>), consider the function iterate:
iterate :: (a -> a) -> a -> [a]
Given a function and an initial value, iterate generates an infinite list by repeatedly applying the function. If we flip the arguments to iterate, we end up with:
flip iterate :: a -> (a -> a) -> [a]
Given the problem with funct <*> (+) was that funct x wouldn't take a Num a => a -> a function, this seems to have a suitable type. And sure enough:
GHCi> take 10 $ (flip iterate <*> (+)) 1
[1,2,3,4,5,6,7,8,9,10]
(On a tangential note, you can leave out the flip if you use (=<<) instead of (<*>). That, however, is a different story.)
As a final aside, neither of the two intuitive pictures lends itself particularly well to the common use case of applicative style expressions such as:
(+) <$> (^2) <*> (^3)
To use the intuitive pictures there, you'd have to account for how (<$>) for functions is (.), which murks things quite a bit. It is easier to just see the entire thing as lifted application instead: in this example, we are adding up the results of (^2) and (^3). The equivalent spelling as...
liftA2 (+) (^2) (^3)
... somewhat emphasises that. Personally, though, I feel one possible disadvantage of writing liftA2 in this setting is that, if you apply the resulting function right in the same expression, you end up with something like...
liftA2 (+) (^2) (^3) 5
... and seeing liftA2 followed by three arguments tends to make my brain tilt.
You can view the function monad as a container. Note that it's really a separate monad for every argument-type, so we can pick a simple example: Bool.
type M a = Bool -> a
This is equivalent to
data M' a = M' { resultForFalse :: a
, resultForTrue :: a }
and the instances could be defined
instance Functor M where instance Functor M' where
fmap f (M g) = M g' fmap f (M' gFalse gTrue) = M g'False g'True
where g' False = f $ g False where g'False = f $ gFalse
g' True = f $ g True g'True = f $ gTrue
and similar for Applicative and Monad.
Of course this exhaustive case-listing definition would become totally impractical for argument-types with more than a few possible values, but it's always the same principle.
But the important thing to take away is that the instances are always specific for one particular argument. So, Bool -> Int and Bool -> String belong to the same monad, but Int -> Int and Char -> Int do not. Int -> Double -> Int does belong to the same monad as Int -> Int, but only if you consider Double -> Int as an opaque result type which has nothing to do with the Int-> monad.
So, if you're considering something like a -> a -> a -> a then this is not really a question about applicatives/monads but about Haskell in general. And therefore, you shouldn't expect that the monad=container picture gets you anywhere. To understand a -> a -> a -> a as a member of a monad, you need to pick out which of the arrows you're talking about; in this case it's only the leftmost one, i.e. you have the value M (a->a->a) in the type M=(a->) monad. The arrows between a->a->a do not participate in the monadic action in any way; if they do in your code, then it means you're actually mixing multiple monads together. Before you do that, you should understand how a single monad works, so stick to examples with only a single function arrow.

Universal container conversion? if from Foldable to Alternative?

For instance Alternative [], (<|>) = (++). So I regarded (<|>) as some kind of splicer, resulting in seemingly almost-universal container converter:
-- (<|>) = generalization of (++)
(<|) :: Alternative f => x -> f x -> f x
x <| xs = pure x <|> xs
conv :: (Foldable t, Alternative f) => t x -> f x
conv = foldr (<|) empty
Indeed, I was able to generalize all functions from Data.List, here's some:
-- fmap = generalization of map
reverse :: (Foldable t, Alternative f) => t a -> f a
reverse = getAlt . getDual . foldMap (Dual . Alt . pure)
-- asum = generalization of concat
asumMap :: (Foldable t, Alternative f) => (a -> f b) -> t a -> f b -- generalization of concatMap
asumMap f = getAlt . foldMap (Alt . f)
splitAt :: (Foldable t, Alternative f, Alternative g) => Int -> t a -> (f a, g a)
splitAt n xs = let (_,fs,gs) = foldl' (\(i,z1,z2) x -> if 0 < i then (i-1,z1 . (x <|),z2) else (0,z1,z2 . (x <|))) (n,id,id) xs in (fs empty,gs empty)
Also, this analogy makes some interesting new instances, such as a working applicative functor for functor sums (Data.Functor.Sum):
instance (Foldable f, Applicative f, Alternative g) => Applicative (Sum f g) where
pure = InL . pure
InL f <*> InL x = InL (f <*> x)
InL f <*> InR x = InR (conv f <*> x)
InR f <*> InL x = InR (f <*> conv x)
InR f <*> InR x = InR (f <*> x)
instance (Foldable f, Applicative f, Alternative g) => Alternative (Sum f g) where
empty = InR empty
InL x <|> _ = InL x
InR _ <|> InL y = InL y
InR x <|> InR y = InR (x <|> y)
Is it actually good idea to generalize all functions and make new instances with this analogy, especially for list operations?
EDIT: I'm especially concerned about ambiguous return type. For normal list operations, the return type is deducible from its argument types. But the "universal" version is not, as the return type must be explicitly specified. Is this problem severe enough to regard the analogy dangerous? (Or is there any other problem?)
EDIT 2: If I'm understanding the behavior of foldl' exactly, the time complexity of universal splitAt (shown above) must be Θ(length xs), as foldl' is strict for every elements, right? If yes, that must be a problem, as it's inferior to the regular version's Θ(min n (length xs)).
It is not always a good idea to make functions as polymorphic as theoretically possible, in particular not function arguments. As a rule of thumb: make function results as polymorphic as possible. (Often, the arguments will then already contain some type variables that are used in the result.) Only if you have a particular reason, also give the arguments extra polymorphism.
The reason being: if everything is polymorphic, the compiler has no hints as to what concrete types to choose. Polymorphic results/values are usually ok, because these will generally be bound directly or indirectly to some top-level definition which has an explicit signature, but polymorphic arguments will often only be filled with literals (number literals are polymorphic in Haskell, and strings/lists can be too) or other polymorphic values, so you end up having to type out lots of explicit local signatures, which tends to be more awkward than having to occasionally toss in an explicit conversion function because something is not polymorphic enough.
This idea with Foldable->Alternative specifically has another problem that the Alternative class is rather frowned upon, having no very solid mathematical backing. It's basically the class of applicative functors which for every instantiation give rise to a Monoid. Well, that can also be expressed directly, by demanding Monoid itself. The “universal container conversion function” thus already exists, it is foldMap pure.

(r ->) applicative functor

I am having some trouble understanding how the function instance (->) r of Applicative works in Haskell.
For example if I have
(+) <$> (+3) <*> (*100) $ 5
I know you get the result 508, I sort of understand that you take the result of (5 + 3) and (5 * 100) and you apply the (+) function to both of these.
However I do not quite understand what is going on. I assume that the expression is parenthesized as follows:
((+) <$> (+3)) <*> (*100)
From my understanding what is happening is that your mapping (+) over the eventual result of (+3) and then you are using the <*> operator to apply that function to the eventual result of (*100)
However I do not understand the implementation of <*> for the (->) r instance and why I cannot write:
(+3) <*> (*100)
How does the <*>, <$> operator work when it comes to (->) r?
<$> is just another name for fmap and its definition for (->) r is (.) (the composition operator):
intance Functor ((->) r) where
fmap f g = f . g
You can basically work out the implementation for <*> just by looking at the types:
instance Applicative ((->) r) where
(<*>) :: (r -> a -> b) -> (r -> a) -> (r -> b)
f <*> g = \x -> f x (g x)
You have a function from r to a to b and a function from r to a. You want a funtion from r to b as a result. First thing you know is you return a function:
\x ->
Now you want to apply f since it is the only item which may return a b:
\x -> f _ _
Now the arguments for f are of type r and a. r is simply x (since it alrady is of type r and you can get an a by applying g to x:
\x -> f x (g x)
Aaand you're done. Here's a link to the implementation in Haskell's Prelude.
Consider the type signature of <*>:
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
Compare this to the type signature for ordinary function application, $:
($) :: (a -> b) -> a -> b
Notice that they are extremely similar! Indeed, the <*> operator effectively generalizes application so that it can be overloaded based on the types involved. This is easy to see when using the simplest Applicative, Identity:
ghci> Identity (+) <*> Identity 1 <*> Identity 2
Identity 3
This can also be seen with slightly more complicated applicative functors, such as Maybe:
ghci> Just (+) <*> Just 1 <*> Just 2
Just 3
ghci> Just (+) <*> Nothing <*> Just 2
Nothing
For (->) r, the Applicative instance performs a sort of function composition, which produces a new function that accepts a sort of “context” and threads it to all of the values to produce the function and its arguments:
ghci> ((\_ -> (+)) <*> (+ 3) <*> (* 100)) 5
508
In the above example, I have only used <*>, so I’ve explicitly written out the first argument as ignoring its argument and always producing (+). However, Applicative typeclass also includes the pure function, which has the same purpose of “lifting” a pure value into an applicative functor:
ghci> (pure (+) <*> (+ 3) <*> (* 100)) 5
508
In practice, though, you will rarely see pure x <*> y because it is precisely equivalent to x <$> y by the Applicative laws, since <$> is just an infix synonym for fmap. Therefore, we have the common idiom:
ghci> ((+) <$> (+ 3) <*> (* 100)) 5
508
More generally, if you see any expression that looks like this:
f <$> a <*> b
…you can read it more or less like the ordinary function application f a b, except in the context of a particular Applicative instance’s idioms. In fact, an original formulation of Applicative proposed the idea of “idiom brackets”, which would add the following as syntactic sugar for the above expression:
(| f a b |)
However, Haskellers seem to be satisfied enough with the infix operators that the benefits of adding the additional syntax has not been deemed worth the cost, so <$> and <*> remain necessary.
Let's take a look at the types of these functions (and the definitions that we automatically get along with them):
(<$>) :: (a -> b) -> (r -> a) -> r -> b
f <$> g = \x -> f (g x)
(<*>) :: (r -> a -> b) -> (r -> a) -> r -> b
f <*> g = \x -> f x (g x)
In the first case, <$>, is really just function composition. A simpler definition would be (<$>) = (.).
The second case is a little more confusing. Our first input is a function f :: r -> a -> b, and we need to get an output of type b. We can provide x :: r as the first argument to f, but the only way we can get something of type a for the second argument is by applying g :: r -> a to x :: r.
As an interesting aside, <*> is really the S function from SKI combinatory calculus, whereas pure for (-> r) is the K :: a -> b -> a (constant) function.
As a Haskell newbie myself, i'll try to explain the best way i can
The <$> operator is the same as mapping a function on to another function.
When you do this:
(+) <$> (+3)
You are basically doing this:
fmap (+) (+3)
The above will call the Functor implementation of (->) r which is the following:
fmap f g = (\x -> f (g x))
So the result of fmap (+) (+3) is (\x -> (+) (x + 3))
Note that the result of this expression has a type of a -> (a -> a)
Which is an applicative! That is why you can pass the result of (+) <$> (+3) to the <*> operator!
Why is it an applicative you might ask? Lets look the at the <*> definition:
f (a -> b) -> f a -> f b
Notice that the first argument matches our returned function definition a -> (a -> a)
Now if we look at the <*> operator implementation, it looks like this:
f <*> g = (\x -> f x (g x))
So when we put all those pieces together, we get this:
(+) <$> (+3) <*> (+5)
(\x -> (+) (x + 3)) <*> (+5)
(\y -> (\x -> (+) (x + 3)) y (y + 5))
(\y -> (+) (y + 3) (y + 5))
The (->) e Functor and Applicative instances tend to be a bit confusing. It may help to view (->) e as an "undressed" version of Reader e.
newtype Reader e a = Reader
{ runReader :: e -> a }
The name e is supposed to suggest the word "environment". The type Reader e a should be read as "a computation that produces a value of type a given an environment of type e".
Given a computation of type Reader e a, you can modify its output:
instance Functor (Reader e) where
fmap f r = Reader $ \e -> f (runReader r e)
That is, first run the computation in the given environment, then apply the mapping function.
instance Applicative (Reader e) where
-- Produce a value without using the environment
pure a = Reader $ \ _e -> a
-- Produce a function and a value using the same environment;
-- apply the function to the value
rf <*> rx = Reader $ \e -> (runReader rf e) (runReader rx e)
You can use the usual Applicative reasoning for this as any other applicative functor.

Confusion Over Applicative (->)

Given that Applicative (->) is implemented as:
instance Applicative ((->) a) where
pure = const
(<*>) f g x = f x (g x)
I am confused how the following works:
pure (+) <*> Just 3
My understanding is that:
f = pure (+)
g = Just 3
Based on that understanding, <*> would become:
-- f x (g x)
(pure (+)) x ((Just 3) x)
But this does not work since (Just 3) takes no parameters. So I apparently must be unaware of something, though I am not sure what that is.
I am baffled as to how this happens:
Prelude> :t pure (+) <*> Just 3
pure (+) <*> Just 3 :: Num a => Maybe (a -> a)
Please explain how this works. Doing the steps manually, based on my understanding of things, I am not able to reach the same outcome as ghci.
Since the right-hand-side argument to <*> is Just 3, then the Applicative instance being used must be that of Maybe, not of functions. So, the left-hand side must be a Maybe as well, thus pure (+) == Just (+). Now you can see how <*> combines these: it unwraps the two Just constructors, applies the function, and puts the result back into a Just: this is the same as Just ((+) 3), or Just (3 +). And as you can see in ghci, those two things have the same type.

What is this special functor structure called?

Suppose that F is an applicative functor with the additional laws (with Haskell syntax):
pure (const ()) <*> m === pure ()
pure (\a b -> (a, b)) <*> m <*> n === pure (\a b -> (b, a)) <*> n <*> m
pure (\a b -> (a, b)) <*> m <*> m === pure (\a -> (a, a)) <*> m
What is the structure called if we omit (3.)?
Where can I find more info on these laws/structures?
Comments on comments
Functors which satisfy (2.) are often called commutative.
The question is now, whether (1.) implies (2.) and how these structures can be described.
I am especially interested in structures which satisfies (1-2.) but not (3.)
Examples:
The reader monad satisfies (1-3.)
The writer monad on a commutative monoid satisfies only (2.)
The monad F given below satisfies (1-2.) but not (3.)
Definition of F:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE RankNTypes #-}
import Control.Monad.State
newtype X i = X Integer deriving (Eq)
newtype F i a = F (State Integer a) deriving (Monad)
new :: F i (X i)
new = F $ modify (+1) >> gets X
evalF :: (forall i . F i a) -> a
evalF (F m) = evalState m 0
We export only the types X, F, new, evalF, and the instances.
Check that the following holds:
liftM (const ()) m === return ()
liftM2 (\a b -> (a, b)) m n === liftM2 (\a b -> (b, a)) n m
On the other hand, liftM2 (,) new new cannot be replaced by liftM (\a -> (a,a)) new:
test = evalF (liftM (uncurry (==)) $ liftM2 (,) new new)
/= evalF (liftM (uncurry (==)) $ liftM (\a -> (a,a)) new)
Comments on C. A. McCann's answer
I have a sketch of proof that (1.) implies (2.)
pure (,) <*> m <*> n
=
pure (const id) <*> pure () <*> (pure (,) <*> m <*> n)
=
pure (const id) <*> (pure (const ()) <*> n) <*> (pure (,) <*> m <*> n)
=
pure (.) <*> pure (const id) <*> pure (const ()) <*> n <*> (pure (,) <*> m <*> n)
=
pure const <*> n <*> (pure (,) <*> m <*> n)
= ... =
pure (\_ a b -> (a, b)) <*> n <*> m <*> n
= see below =
pure (\b a _ -> (a, b)) <*> n <*> m <*> n
= ... =
pure (\b a -> (a, b)) <*> n <*> m
=
pure (flip (,)) <*> n <*> m
Observation
For the missing part first consider
pure (\_ _ b -> b) <*> n <*> m <*> n
= ... =
pure (\_ b -> b) <*> n <*> n
= ... =
pure (\b -> b) <*> n
= ... =
pure (\b _ -> b) <*> n <*> n
= ... =
pure (\b _ _ -> b) <*> n <*> m <*> n
Lemma
We use the following lemma:
pure f1 <*> m === pure g1 <*> m
pure f2 <*> m === pure g2 <*> m
implies
pure (\x -> (f1 x, f2 x)) m === pure (\x -> (g1 x, g2 x)) m
I could prove this lemma only indirectly.
The missing part
With this lemma and the first observation we can prove
pure (\_ a b -> (a, b)) <*> n <*> m <*> n
=
pure (\b a _ -> (a, b)) <*> n <*> m <*> n
which was the missing part.
Questions
Is this proved already somewhere (maybe in a generalized form)?
Remarks
(1.) implies (2.) but otherwise (1-3.) are independent.
To prove this, we need two more examples:
The monad G given below satisfies (3.) but not (1-2.)
The monad G' given below satisfies (2-3.) but not (1.)
Definition of G:
newtype G a = G (State Bool a) deriving (Monad)
putTrue :: G ()
putTrue = G $ put True
getBool :: G Bool
getBool = G get
evalG :: G a -> a
evalG (G m) = evalState m False
We export only the type G, putTrue, getBool, evalG, and the Monad instance.
The definition of G' is similar to the definition of G with the following differences:
We define and export execG:
execG :: G' a -> Bool
execG (G m) = execState m False
We do not export getBool.
Your first law is a very strong requirement; it implies that the functor can have no distinguished "shape" independent of the parametric portion. This rules out any functor that contains extra values (State, Writer, &c.) as well as any functor using sum types (Either, [], &c.). So this limits us to things like fixed-size containers.
Your second law requires commutativity, which means that order of nesting (that is, functor composition) doesn't matter. This might actually be implied by the first law, since we already know that the functor can't contain any information other than the parametric values, and you explicitly require preservation of that here.
Your third law requires that the functor be idempotent as well, which means that nesting something within itself using fmap is equivalent to itself. This probably implies that if the functor is a monad as well, join involves some sort of "taking the diagonal". Basically, this means that liftA2 (,) should behave like zip, not a cartesian product.
The second and third together imply that however many "primitives" the functor might have, any composition is equivalent to combining at most one of each primitive, in any order. And the first implies that if you throw out the parametric information, any combination of primitives is the same as using none at all.
In summary, I think what you have is the class of functors isomorphic to Reader. That is, functors where f a describes values of type a indexed by some other type, such as a subset of the natural numbers (for fixed-size containers) or an arbitrary type (as with Reader).
I'm not sure how to convincingly prove most of the above, unfortunately.

Resources