Is the only `FlippyFloppyMorphism` `const mempty`? - haskell

In Haskell, we have the interesting fact that any type constructor f :: * -> * which is simultaneously a Functor and a Contravariant is phantom in its type parameter:
phantom :: (Functor f, Contravariant f) => f x -> f y
Another way to put this is that every type constructor that is simultaneously a Functors and a Contravariant is naturally isomorphic to Const x, for some x.
This implies that the "only" way (up to isomorphism) to instantiate the class:
class FlippyFloppyFunctor f
where
ffmap :: Either (y -> x) (x -> y) -> f x -> f y
so that it obeys the functor laws:
ffmap (Left id) = id
ffmap (Right id) = id
ffmap (Left (g . f)) = ffmap (Left f) . ffmap (Left g)
ffmap (Right (f . g)) = ffmap (Right f) . ffmap (Right g)
is:
weirdmap :: Either (y -> x) (x -> y) -> Const r x -> Const r y
weirdmap = const $ \(Const x) -> Const x
i.e. modulo newtypes, const id.
I find it difficult to understand why this is the only function of its type that satisfies the constraints, although I can sort of understand various informal arguments involving absurd :: Void -> a/discard :: a -> () as to why the existence of such a map implies the functor "is phantom" in its type parameter.
To understand it better, I tried to simplify the problem. Instead of thinking about FlippyFloppyFunctor, let's think about:
class (Monoid a, Monoid b) => FlippyFloppyMorphism a b
where
ffmorph :: Either a a -> b
with analogous laws:
ffmorph (Left mempty) = mempty
ffmorph (Right mempty) = mempty
ffmorph (Left (y <> x)) = ffmorph (Left x) <> ffmorph (Left y)
ffmorph (Right (x <> y)) = ffmorph (Right x) <> ffmorph (Right y)
Assuming that a and b are non-commutative monoids, is it still true that the only lawful implementation of FlippyFloppyMorphism is const mempty? Is it still possible to explain why the morphism must be "phantom" in the input monoids, without having a Void or a () to refer to?

It seems to me that the answer in the general case is "no", because monoids can be commutative.
If the monoid is commutative, then Dual a is the same monoid as a, and Either a a is the same as a, and hence we just degenerate to asking whether ffmorph is the only monoid homomorphism a -> b. The answer is "no".
For example, for the commutative monoid of addition, we have replicate 'a' :: Either (Sum Int) (Sum Int) -> String, where:
replicateA (Left 0) = ""
replicateA (Right 0) = ""
replicateA (Left (y + x)) = replicateA (Left x) ++ replicateA (Left y)
replicateA (Right (x + y)) = replicateA (Left x) ++ replicateA (Left y)
However, I think it might be the case that for _non_commutative monoids, the only possible implementation is const mempty (which I still don't have a proof for).

Related

What does this law of applicative mean?

Applicative is declared as
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
One of applicative's laws is:
x <*> y <*> z = ( pure (.) <*> x <*> y) <*> z
where (.) is composition between functions:
(.) :: (b -> c) -> (a -> b) -> (a -> c)
f . g = \x -> f (g x)
On the right hand side of the law,
does pure (.) have type f((b -> c) -> (a -> b) -> (a -> c))?
does x have type f(b->c)?
does y have type f(a->b)?
does z have type f(a)?
On the left hand side of the law,
does x have type f(a->b->c)?
does y have type f(a)?
does z have type f(b)?
Thanks.
The applicative laws are easier understood in the equivalent monoidal functor representation:
class Functor f => Monoidal f where
pureUnit :: f ()
fzip :: f a -> f b -> f (a,b)
--pure x = fmap (const x) pureUnit
--fs<*>xs = fmap (\(f,x)->f x) $ fzip fs xs
--pureUnit = pure ()
--fzip l r = (,) <$> l <*> r
Then, the law you're asking about is this:
fzip x (fzip y z) ≅ fzip (fzip x y) z
where by p ≅ q I mean, equivalent up to re-association of the tuple type, i.e. explicitly
fzip x (fzip y z) ≡ fmap (\((a,b),c)->(a,(b,c))) $ fzip (fzip x y) z
So this is really just an associative law. Even better visible when written with an infix (⋎) = fzip:
x ⋎ (y ⋎ z) ≅ (x ⋎ y) ⋎ z
Stating the law again for ease of reference (which I have corrected by putting the parenthese in, `(<*>) is left associative so the ones on the LHS of the equality are necessary):
x <*> (y <*> z) = ( pure (.) <*> x <*> y) <*> z
let's start with your first question:
On the right hand side of the law,
does pure (.) have type f((b -> c) -> (a -> b) -> (a -> c))?
Yes it does. (.) has type (b -> c) -> (a -> b) -> (a -> c), so pure (.) must have type "f of that".
We can use this to determine the types of the other identifiers here. In the expression m <*> n, m and n have the general types f (a -> b) and f a. So if we take m as (.), which has the type shown above, we see that n - which corresponds to x on the RHS of the equality - must have type f (b -> c). And then pure (.) <*> x will have type f ((a -> b) -> (a -> c)), which by the same reasoning means y will have type f (a -> b). This produces a type of f (a -> c) for ( pure (.) <*> x <*> y) and of f a for z - and thus an overall result type, for the whole RHS (and therefore also the whole LHS) of f c.
So to summarise, just from analysing the RHS, we see that:
x :: f (b -> c)
y :: f (a -> b)
z :: f a
It's now easy to check that these work out on the LHS too - y <*> z will have type f b, so x <*> (y <*> z) will have type f c.
I note that there's nothing clever involved in the above, it's just simple type algebra, which can be carried out without any advanced understanding.

Which Haskell Functors are equivalent to the Reader functor

Some Haskell functors F a are obviously isomorphic to T -> a for some type T, e.g.
data Pair a = Pair a a -- isomorphic to Bool -> a
data Reader r a = Reader (r -> a) -- isomorphic to r -> a (duh!)
data Identity a = Identity a -- isomorphic to () -> a
data Phantom a = Phantom -- isomorphic to void -> a
(These isomorphism are only up to strictness, and considering only finite data structures.)
So in general, how can we characterize functors where this is possible?
And is the question “Which Haskell Functors are representable?” the same question?
And Noah said unto the animals "Go forth and multiply!", but the snakes said
"We cannot multiply, for we are adders.", so Noah took wood from the Ark and,
shaping it, said "I am building you a table of logs.".
Representable functors are sometimes also called "Naperian" functors (it's Peter Hancock's term: Hank's a denizen of the same part of Edinburgh as John Napier, of logarithmic fame) because when F x ~= T -> x, and remembering that, combinatorially, T -> x is "x to the power T", we see that T is in some sense Log F.
The first thing to note is that F () ~= T -> () ~= (). That tells us there is only one shape. Functors which offer us a choice of shape cannot be Naperian, because they don't give a uniform presentation of the positions for data. That means [] is not Naperian, because different-length lists have positions represented by different types. However, an infinite Stream has positions given by the natural numbers.
Correspondingly, given any two F structures, their shapes are bound to match, so they have a sensible zip, giving us the basis for an Applicative F instance.
Indeed, we have
a -> p x
=====================
(Log p, a) -> x
making p a right adjoint, so p preserves all limits, hence unit and products in particular, making it a monoidal functor, not just a lax monoidal functor. That is, the alternative presentation of Applicative has operations which are isomorphisms.
unit :: () ~= p ()
mult :: (p x, p y) ~= p (x, y)
Let's have a type class for the things. I cook it a bit differently from the Representable class.
class Applicative p => Naperian p where
type Log p
logTable :: p (Log p)
project :: p x -> Log p -> x
tabulate :: (Log p -> x) -> p x
tabulate f = fmap f logTable
-- LAW1: project logTable = id
-- LAW2: project px <$> logTable = px
We have a type Log f, representing at least some of the positions inside an f; we have a logTable, storing in each position the representative of that position, acting like a 'map of an f' with placenames in each place; we have a project function extracting the data stored at a given position.
The first law tells us that the logTable is accurate for all the positions which are represented. The second law tells us that we have represented all the positions. We may deduce that
tabulate (project px)
= {definition}
fmap (project px) logTable
= {LAW2}
px
and that
project (tabulate f)
= {definition}
project (fmap f logTable)
= {free theorem for project}
f . project logTable
= {LAW1}
f . id
= {composition absorbs identity}
f
We could imagine a generic instance for Applicative
instance Naperian p => Applicative p where
pure x = fmap (pure x) logTable
pf <$> px = fmap (project pf <*> project ps) logTable
which is as much as to say that p inherits its own K and S combinators from the usual K and S for functions.
Of course, we have
instance Naperian ((->) r) where
type Log ((->) r) = r -- log_x (x^r) = r
logTable = id
project = ($)
Now, all the limit-like constructions preserve Naperianity. Log maps limity things to colimity things: it calculates left adjoints.
We have the terminal object and products.
data K1 x = K1
instance Applicative K1 where
pure x = K1
K1 <*> K1 = K1
instance Functor K1 where fmap = (<*>) . pure
instance Naperian K1 where
type Log K1 = Void -- "log of 1 is 0"
logTable = K1
project K1 nonsense = absurd nonsense
data (p * q) x = p x :*: q x
instance (Applicative p, Applicative q) => Applicative (p * q) where
pure x = pure x :*: pure x
(pf :*: qf) <*> (ps :*: qs) = (pf <*> ps) :*: (qf <*> qs)
instance (Functor p, Functor q) => Functor (p * q) where
fmap f (px :*: qx) = fmap f px :*: fmap f qx
instance (Naperian p, Naperian q) => Naperian (p * q) where
type Log (p * q) = Either (Log p) (Log q) -- log (p * q) = log p + log q
logTable = fmap Left logTable :*: fmap Right logTable
project (px :*: qx) (Left i) = project px i
project (px :*: qx) (Right i) = project qx i
We have identity and composition.
data I x = I x
instance Applicative I where
pure x = I x
I f <*> I s = I (f s)
instance Functor I where fmap = (<*>) . pure
instance Naperian I where
type Log I = () -- log_x x = 1
logTable = I ()
project (I x) () = x
data (p << q) x = C (p (q x))
instance (Applicative p, Applicative q) => Applicative (p << q) where
pure x = C (pure (pure x))
C pqf <*> C pqs = C (pure (<*>) <*> pqf <*> pqs)
instance (Functor p, Functor q) => Functor (p << q) where
fmap f (C pqx) = C (fmap (fmap f) pqx)
instance (Naperian p, Naperian q) => Naperian (p << q) where
type Log (p << q) = (Log p, Log q) -- log (q ^ log p) = log p * log q
logTable = C (fmap (\ i -> fmap (i ,) logTable) logTable)
project (C pqx) (i, j) = project (project pqx i) j
Naperian functors are closed under greatest fixpoints, with their logarithms being the corresponding least fixpoints. E.g., for streams, we have
log_x (Stream x)
=
log_x (nu y. x * y)
=
mu log_xy. log_x (x * y)
=
mu log_xy. log_x x + log_x y
=
mu log_xy. 1 + log_xy
=
Nat
It's a bit fiddly to render that in Haskell without introducing Naperian bifunctors (which have two sets of positions for two sorts of things), or (better) Naperian functors on indexed types (which have indexed positions for indexed things). What's easy, though, and hopefully gives the idea, is the cofree comonad.
data{-codata-} CoFree p x = x :- p (CoFree p x)
-- i.e., (I * (p << CoFree p)) x
instance Applicative p => Applicative (CoFree p) where
pure x = x :- pure (pure x)
(f :- pcf) <*> (s :- pcs) = f s :- (pure (<*>) <*> pcf <*> pcs)
instance Functor p => Functor (CoFree p) where
fmap f (x :- pcx) = f x :- fmap (fmap f) pcx
instance Naperian p => Naperian (CoFree p) where
type Log (CoFree p) = [Log p] -- meaning finite lists only
logTable = [] :- fmap (\ i -> fmap (i :) logTable) logTable
project (x :- pcx) [] = x
project (x :- pcx) (i : is) = project (project pcx i) is
We may take Stream = CoFree I, giving
Log Stream = [Log I] = [()] ~= Nat
Now, the derivative D p of a functor gives its type of one-hole context, telling us i) the shape of a p, ii) the position of the hole, iii) the data that are not in the hole. If p is Naperian, there is no choice of shape, so putting trivial data in the non-hole positions, we find that we just get the position of the hole.
D p () ~= Log p
More on that connection can be found in this answer of mine about tries.
Anyhow, Naperian is indeed a funny local Scottish name for Representable, which are the things for which you can build a table of logs: they are the constructions characterized entirely by projection, offering no choice of 'shape'.

Implementing Monoidal in terms of Applicative

Typeclassopedia presents the following exercise:
Implement pure and (<*>) in terms of unit and (**), and vice versa.
Here's Monoidal and MyApplicative:
class Functor f => Monoidal f where
u :: f () -- using `u` rather than `unit`
dotdot :: f a -> f b -> f (a,b) -- using instead of `(**)`
class Functor f => MyApplicative f where
p :: a -> f a -- using instead of `pure`
apply :: f (a -> b) -> f a -> f b -- using instead of `(<**>)`
First, let me show the Maybe-like data type:
data Option a = Some a
| None deriving Show
Then, I defined instance MyApplicative Option:
instance MyApplicative Option where
p = Some
apply None _ = None
apply _ None = None
apply (Some g) f = fmap g f
Finally, my attempt at implementing Monoidal Option in terms of p and apply of MyApplicative:
instance Monoidal Option where
u = p ()
dotdot None _ = None
dotdot _ None = None
dotdot (Some x) (Some y) = Some id <*> Some (x, y)
Is this right? My implementation of dotdot with apply doesn't seem
instance Monoidal Option where
u = p ()
dotdot None _ = None
dotdot _ None = None
dotdot (Some x) (Some y) = apply (Some id) (Some (x, y))
In particular, I'm curious about how to properly implement dotdot :: f a -> f b -> f (a, b) with Applicative's (<*>) - in my case it's apply.
Applicative is a neat alternative presentation of Monoidal. Both typeclasses are equivalent, and you can convert between the two without considering a specific data type like Option. The "neat alternative presentation" for Applicative is based on the following two equivalencies
pure a = fmap (const a) unit
unit = pure ()
ff <*> fa = fmap (\(f,a) -> f a) $ ff ** fa
fa ** fb = pure (,) <*> fa <*> fb
The trick to get this "neat alternative presentation" for Applicative is the same as the trick for zipWith - replace explicit types and constructors in the interface with things that the type or constructor can be passed into to recover what the original interface was.
unit :: f ()
is replaced with pure which we can substitute the type () and the constructor () :: () into to recover unit.
pure :: a -> f a
pure () :: f ()
And similarly (though not as straightforward) for substituting the type (a,b) and the constructor (,) :: a -> b -> (a,b) into liftA2 to recover **.
liftA2 :: (a -> b -> c) -> f a -> f b -> f c
liftA2 (,) :: f a -> f b -> f (a,b)
Applicative then gets the nice <*> operator by lifting function application ($) :: (a -> b) -> a -> b into the functor.
(<*>) :: f (a -> b) -> f a -> f b
(<*>) = liftA2 ($)
Getting from <*> back to liftA2 is common enough that liftA2 is included in Control.Applicative. The <$> is infix fmap.
liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c
liftA2 f a b = f <$> a <*> b

How can holes and contexts be implemented for higher-kinded types in a lens style uniplate library?

András Kovács proposed this question in response to an answer to a previous question.
In a lens-style uniplate library for types of kind * -> * based on the class
class Uniplate1 f where
uniplate1 :: Applicative m => f a -> (forall b. f b -> m (f b)) -> m (f a)
analogous to the class for types of kind *
class Uniplate on where
uniplate :: Applicative m => on -> (on -> m on) -> m on
is it possible to implement analogs to contexts and holes, which both have the type Uniplate on => on -> [(on, on -> on)] without requiring Typeable1?
It's clear that this could be implemented in the old-style of the uniplate library which used Str to represent the structure of the data by returning a structure with a type-level list of the types of the children.
A hole could be represented by the following data type, which would replace (on, on -> on) in the signatures for contexts and holes
data Hole f a where
Hole :: f b -> (f b -> f a) -> Hole f a
holes :: Uniplate1 f => f a -> [Hole f a]
...
However, it is unclear if there is an implementation for holes which doesn't require Typeable1.
The suggested type Hole is needlessly restrictive in the return type of the function. The following type can represent everything the former Hole represents, and more, without loss of any type information.
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE GADTs #-}
data Hole f a where
Hole :: f b -> (f b -> a) -> Hole f a
If we need to have a return type of f a, we can use Hole f (f a) to represent it. Since we will be using Holes a lot, it'd be nice to have a few utility functions. Because the return type of the function in Hole is no longer constrained to be in f, we can make a Functor instance for it
instance Functor (Hole f) where
fmap f (Hole b g) = Hole b (f . g)
contexts1 can be written for either version of Hole by replacing the constructors for tuples in the uniplate library's contexts with Hole:
contexts1 :: Uniplate1 f => f a -> [Hole f (f a)]
contexts1 x = Hole x id : f (holes1 x)
where
f xs = [ Hole y (ctx . context)
| Hole child ctx <- xs
, Hole y context <- contexts1 child]
holes1 is trickier, but can still be made by modifying holes from the uniplate library. It requires a new Replace1 Applicative Functor that uses Hole instead of a tuple. Everyhwere the second field of the tuple was modified by second (f .) we replace with fmap f for the Hole.
data Replace1 f a = Replace1 {replaced1 :: [Hole f a], replacedValue1 :: a}
instance Functor (Replace1 f) where
fmap f (Replace1 xs v) = Replace1 (map (fmap f) xs) (f v)
instance Applicative (Replace1 f) where
pure v = Replace1 [] v
Replace1 xs1 f <*> Replace1 xs2 v = Replace1 (ys1 ++ ys2) (f v)
where ys1 = map (fmap ($ v)) xs1
ys2 = map (fmap (f)) xs2
holes1 :: Uniplate1 f => f a -> [Hole f (f a)]
holes1 x = replaced1 $ descendM1 (\v -> Replace1 [Hole v id] v) x
decendM1 is defined in the preceding answer. Replace and Replace1 can be unified; how to do so is described after the examples.
Let's try some examples in terms of the code in the previous question. The following utility functions on Holes will be useful.
onHole :: (forall b. f b -> c) -> Hole f a -> c
onHole f (Hole x _) = f x
inHole :: (forall b. f b -> f b) -> Hole f a -> a
inHole g (Hole x f) = f . g $ x
Examples
We'll use the following example data and function, based on the code from the preceding questions:
example = If (B True) (I 2 `Mul` I 3) (I 1)
zero :: Expression b -> Expression b
zero x = case x of
I _ -> I 0
B _ -> B False
Add _ _ -> I 0
Mul _ _ -> I 0
Eq _ _ -> B False
And _ _ -> B False
Or _ _ -> B False
If _ a _ -> zero a
Holes
sequence_ . map (onHole print) . holes1 $ example
B True
Mul (I 2) (I 3)
I 1
Contexts
sequence_ . map (onHole print) . contexts1 $ example
If (B True) (Mul (I 2) (I 3)) (I 1)
B True
Mul (I 2) (I 3)
I 2
I 3
I 1
Replacement of each context
sequence_ . map print . map (inHole zero) . contexts1 $ example
I 0
If (B False) (Mul (I 2) (I 3)) (I 1)
If (B True) (I 0) (I 1)
If (B True) (Mul (I 0) (I 3)) (I 1)
If (B True) (Mul (I 2) (I 0)) (I 1)
If (B True) (Mul (I 2) (I 3)) (I 0)
Unifying Replace
The Replace Applicative Functor can be refactored so that it doesn't know about the type of holes for either Uniplate or Uniplate1, and instead only knows that the hole is a Functor. Holes for Uniplate were using the type (on, on -> a) and essentially using fmap f = second (f .); this is the composition of the (on, ) and on-> functors.
Instead of grabbing Compose from the transformers library, we'll make a new type for a Hole for Uniplate, which will make the example code here be more consistent and self-contained.
data Hole on a = Hole on (on -> a)
instance Functor (Hole on) where
fmap f (Hole on g) = Hole on (f . g)
We'll rename our Hole from before to Hole1.
data Hole1 f a where
Hole1 :: f b -> (f b -> a) -> Hole1 f a
instance Functor (Hole1 f) where
fmap f (Hole1 b g) = Hole1 b (f . g)
Replace can drop all knowledge of either type of hole.
data Replace f a = Replace {replaced :: [f a], replacedValue :: a}
instance Functor f => Functor (Replace f) where
fmap f (Replace xs v) = Replace (map (fmap f) xs) (f v)
instance Functor f => Applicative (Replace f) where
pure v = Replace [] v
Replace xs1 f <*> Replace xs2 v = Replace (ys1 ++ ys2) (f v)
where ys1 = map (fmap ($ v)) xs1
ys2 = map (fmap (f)) xs2
Both holes and holes1 can be implemented in terms of the new Replace.
holes :: Uniplate on => on -> [Hole on on]
holes x = replaced $ descendM (\v -> Replace [Hole v id] v) x
holes1 :: Uniplate1 f => f a -> [Hole1 f (f a)]
holes1 x = replaced $ descendM1 (\v -> Replace [Hole1 v id] v) x

Parse error in pattern: f . g in fmap (f . g) = fmap f . fmap g

Parse error in pattern: f . g
i am a beginner, where is wrong?
(f . g) x = f (g x)
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Functor g where
fmap :: (a -> b) -> f a -> f b
instance Functor F where
fmap id = id
fmap (f . g) = fmap f . fmap g
When you make an instance of Functor, you should prove the side condition that
fmap id = id
and
fmap (f . g) = fmap f . fmap g
(Technically the latter comes for free given the types involved and the former law, but it is still a good exercise.)
You can't do this just by saying
fmap id = id
but instead you use this as a reasoning tool -- once you have proven it.
That said, the code that you have written doesn't make sense for a number of reasons.
(f . g) x = f (g x)
Since this is indented, I'm somewhat unclear if this is intended to be a definition for (.), but that is already included in the Prelude, so you need not define it again.
class Functor f where
fmap :: (a -> b) -> f a -> f b
This definition is also provided for you in the Prelude.
class Functor g where
fmap :: (a -> b) -> f a -> f b
But then you define the class again, but here it has mangled the signature of fmap, which would have to be
fmap :: (a -> b) -> g a -> g b
But as you have another definition of Functor right above (and the Prelude has still another, you couldn't get that to compile)
Finally, your
instance Functor F where
fmap id = id
fmap (f . g) = fmap f . fmap g
makes up a name F for a type that you want to make into an instance of Functor, and then tries to give the laws as an implementation, which isn't how it works.
Let us take an example of how it should work.
Consider a very simple functor:
data Pair a = Pair a a
instance Functor Pair where
fmap f (Pair a b) = Pair (f a) (f b)
now, to prove fmap id = id, let us consider what fmap id and id do pointwise:
fmap id (Pair a b) = -- by definition
Pair (id a) (id b) = -- by beta reduction
Pair a (id b) = -- by beta reduction
Pair a b
id (Pair a b) = -- by definition
Pair a b
So, fmap id = id in this particular case.
Then you can check (though technically given the above, you don't have to) that fmap f . fmap g = fmap (f . g)
(fmap f . fmap g) (Pair a b) = -- definition of (.)
fmap f (fmap g (Pair a b)) = -- definition of fmap
fmap f (Pair (g a) (g b)) = -- definition of fmap
Pair (f (g a)) (f (g b))
fmap (f . g) (Pair a b) = -- definition of fmap
Pair ((f . g) a) ((f . g) b) = -- definition of (.)
Pair (f (g a)) ((f . g) b) = -- definition of (.)
Pair (f (g a)) (f (g b))
so fmap f . fmap g = fmap (f . g)
Now, you can make function composition into a functor.
class Functor f where
fmap :: (a -> b) -> f a -> f b
by partially applying the function arrow constructor.
Note that a -> b and (->) a b mean the same thing, so when we say
instance Functor ((->) e) where
the signature of fmap specializes to
fmap {- for (->) e -} :: (a -> b) -> (->) e a -> (->) e b
which once you have flipped the arrows around looks like
fmap {- for (->) e -} :: (a -> b) -> (e -> a) -> e -> b
but this is just the signature for function composition!
So
instance Functor ((->)e) where
fmap f g x = f (g x)
is a perfectly reasonable definition, or even
instance Functor ((->)e) where
fmap = (.)
and it actually shows up in Control.Monad.Instances.
So all you need to use it is
import Control.Monad.Instances
and you don't need to write any code to support this at all and you can use fmap as function composition as a special case, so for instance
fmap (+1) (*2) 3 =
((+1) . (*2)) 3 =
((+1) ((*2) 3)) =
((+1) (3 * 2)) =
3 * 2 + 1 =
7
Since . is not a data constructor you cannot use it for pattern matching I believe. As far as I can tell there isn't an easy way to do what you're trying, although I'm pretty new to Haskell as well.
let is not used for top-level bindings, just do:
f . g = \x -> f (g x)
But the complaint, as cobbal said, is about fmap (f . g), which isn't valid. Actually, that whole class Functor F where is screwy. The class is already declared, now I think you want to make and instance:
instance Functor F where
fmap SomeConstructorForF = ...
fmap OtherConstructorForF = ...
etc.

Resources