Why does Functor not expose a default implementation of fmap? - haskell

In the Functor class type definition:
class Functor f where
fmap :: (a -> b) -> f a -> f b
Why does fmap not have a default implementation? Something like that:
class Functor f where
fmap :: (a -> b) -> f a -> f b
fmap fn (f a) = (f $ (fn) a)
When I write instances of Functor, I write the same code for each instance manually. Is there a way for me to specify a default implementation?

You probably want this:
{-# LANGUAGE DeriveFunctor #-}
data T1 a = T1 a
deriving Functor
data T2 a = T2 a
deriving Functor
As to why there's no default implementation for functor: your proposal only works if f is the identity functor (up to isomorphism). That is, it works on
data F a = F a
but it is not going to work on
data F a = F a a
or
data F a = F (Int -> a) [a] (Maybe a)
which require more complex fmaps.
While one can not write a default fmap which works in every case, in many simple cases such as the above ones it seems trivial to spot what fmap should be.
Fortunately, we now have derive Functor which covers these simple cases.

Related

Are extensible GADTs a viable solution to the expression problem?

Consider the following wishful program.
{-# LANGUAGE ExtensibleGADTs #-}
data Free a where
Lift :: a -> Free a
data Free (f a) => FreeFunctor f a where
Map :: (a -> b) -> FreeFunctor f a -> FreeFunctor f b
instance Functor (FreeFunctor f) where
fmap = Map
data FreeFunctor f a => FreeApplicative f a where
Apply :: FreeApplicative f (a -> b) -> FreeApplicative f a -> FreeApplicative f b
Pure :: a -> FreeApplicative f a
instance Applicative (FreeApplicative f) where
(<*>) = Apply
pure = Pure
data FreeApplicative m a => FreeMonad m a where
Bind :: FreeMonad m a -> (a -> FreeMonad m b) -> FreeMonad m b
instance Monad (FreeMonad m) where
(>>=) = Bind
This would introduce a notion of substitutability. For example, a FreeApplicative f a can be substituted by a FreeFunctor f a but not a FreeMonad f a. Similarly, a FreeApplicative f a -> Int can be substituted by a FreeMonad f a -> Int but not a FreeFunctor f a -> Int.
The notion of subtyping can be captured using injections.
import Unsafe.Coerce
fromFreeToFreeFunctor :: Free (f a) -> FreeFunctor f a
fromFreeToFreeFunctor = unsafeCoerce
fromFreeFunctorToFreeApplicative :: FreeFunctor f a -> FreeApplicative f a
fromFreeFunctorToFreeApplicative = unsafeCoerce
fromFreeApplicativeToFreeMonad :: FreeApplicative m a -> FreeMonad m a
fromFreeApplicativeToFreeMonad = unsafeCoerce
The compiler would insert these injections as and where required.
I think that this is a good solution to the expression problem. However, the general consensus is that subtype polymorphism would be problematic in Haskell. So, my question is two fold.
Would subtyping, as I described above, be problematic or interfere with type inference in Haskell?
Would extensible GADTs be a viable solution to the expression problem in Haskell?
I haven't defined a precise semantics for extensible GADTs yet. If this seems like something worth pursuing then I'd like to write a GHC extension for this. Just wanted to put this idea out in the wild and get some criticism.

Might laziness also mean a value of function depends on context where it is called?

I'm trying to learn Haskell, and whilst playing with applicative functors, one thing I found puzzles me.
Let's define following function g that returns some functor:
*Main> let g = pure (2*)
*Main> :t g
g :: (Num a, Applicative f) => f (a -> a)
Since a return type is some functor, I can use g as a parameter in both of these functions:
f1 :: (Num a) => [a -> a] -> a
f1 (g:[]) = g 3
f2 :: (Num a) => Maybe (a -> a) -> a
f2 (Just g) = g 4
But it means that a value the function g returns depends also on context in which will be evaluated! (It might be both List and Maybe.) Is this also a property of laziness? Because until now I was thinking about laziness in a way that a value is calculated when is needed, but it is already determined when it is defined (for g in let expression).
As #augustss said, it has nothing to do with laziness but rather the fact that you are working with a typeclass. To make this clearer, you can model typeclasses by explicitly passing along a record packing all the functions the class defines. This technique is called dictionary passing in case you want to look up more info about it.
We start with a few extensions.
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RecordWildCards #-}
And then give the record type packing the functions an Applicative is supposed to have (in practice you'd also have a field saying that f is a Functor but I omit it here for brevity).
data Applicative f =
Applicative { pure :: forall a. a -> f a
, app :: forall a b. f (a -> b) -> f a -> f b
}
And we can define your function g as taking a record saying that f is an Applicative and delivering the behaviour you were describing (I kept Num as a class constraint but, similarly, it could be translated to record passing).
g :: Num a => Applicative f -> f (a -> a)
g Applicative{..} = pure (2*)
Your two functions f1 and f2 are still valid definitions:
f1 :: Num a => [a -> a] -> a
f1 (g:[]) = g 3
f2 :: Num a => Maybe (a -> a) -> a
f2 (Just g) = g 4
Now, we want to apply them to g but there's an issue: g has a function type expecting an Applicative f record being passed. Well, we can define the [] and Maybe instances of Applicative:
applicativeList :: Applicative []
applicativeList =
Applicative { pure = (:[])
, app = \ fs as -> fs >>= \ f -> fmap f as
}
applicativeMaybe :: Applicative Maybe
applicativeMaybe =
Applicative { pure = Just
, app = \ fs as -> fs >>= \ f -> fmap f as
}
And we then have to pick the right one for the application to typecheck ([] for f1 and Maybe for f2):
f1g = f1 (g applicativeList)
f2g = f2 (g applicativeMaybe)

Make Data Type of Kind * -> * That's Not a Functor

Brent Yorgey's Typeclassopedia gives the following exercise:
Give an example of a type of kind * -> * which cannot be made an
instance of Functor (without using undefined).
Please tell me what "cannot be made an instance of Functor" means.
Also, I'd appreciate an example, but perhaps as a spoiler so that you can, please, guide me to the answer.
Let's talk about variances.
Here's the basic notion. Consider the type A -> B. What I want you to imagine is that such a type is similar to "having a B" and also "owing an A". In fact, if you pay back your A you immediately receive your B. Functions are kind of like escrow in that way.
The notion of "having" and "owing" can extend to other types. For instance, the simplest container
newtype Box a = Box a
behaves like this: if you "have" a Box a then you also "have" an a. We consider types which have kind * -> * and "have" their argument to be (covariant) functors and we can instantiate them to Functor
instance Functor Box where fmap f (Box a) = Box (f a)
What happens if we consider the type of predicates over a type, like
newtype Pred a = Pred (a -> Bool)
in this case, if we "have" a Pred a, we actually "owe" an a. This arises from the a being on the left side of the (->) arrow. Where fmap of Functor is defined by passing the function into the container and applying it to all the places where we "have" our inner type, we can't do the same for Pred a since we don't "have" and as.
Instead, we'll do this
class Contravariant f where
contramap :: (a -> b) -> (f b -> f a)
Now that contramap is like a "flipped" fmap? It will allow us to apply the function to the places where we "own" a b in Pred b in order to receive a Pred a. We might call contramap "barter" because it encodes the idea that if you know how to get bs from as then you can turn a debt of bs into a debt of as.
Let's see how it works
instance Contravariant Pred where
contramap f (Pred p) = Pred (\a -> p (f a))
we just run our trade using f prior to passing it on into the predicate function. Wonderful!
So now we have covariant and contravariant types. Technically, these are known as covariant and contravariant "functors". I'll also state immediately that almost always a contravariant functor is not also covariant. This, thus, answers your question: there exist a bunch of contravariant functors which are not able to be instantiated to Functor. Pred is one of them.
There are tricky types which are both contravariant and covariant functors, though. In particular, the constant functors:
data Z a = Z -- phantom a!
instance Functor Z where fmap _ Z = Z
instance Contravariant Z where contramap _ Z = Z
In fact, you can essentially prove that anything which is both Contravariant and Functor has a phantom parameter.
isPhantom :: (Functor f, Contravariant f) => f a -> f b -- coerce?!
isPhantom = contramap (const ()) . fmap (const ()) -- not really...
On the other hand, what happens with a type like
-- from Data.Monoid
newtype Endo a = Endo (a -> a)
In Endo a we both owe and receive an a. Does that mean we're debt free? Well, no, it just means that Endo wants to be both covariant and contravariant and does not have a phantom parameter. The result: Endo is invariant and can instantiate neither Functor nor Contravariant.
A type t of kind * -> * can be made an instance of Functor if and only if it is possible to implement a law-abiding instance of the Functor class for it. So that means you have to implement the Functor class, and your fmap has to obey the Functor laws:
fmap id x == x
fmap f (fmap g x) == fmap (f . g) x
So basically, to solve this, you have to name some type of your choice and prove that there's no lawful implementation of fmap for it.
Let's start with a non-example, to set the tone. (->) :: * -> * -> * is the function type constructor, as seen in function types like String -> Int :: *. In Haskell, you can partially apply type constructors, so you can have types like (->) r :: * -> *. This type is a Functor:
instance Functor ((->) r) where
fmap f g = f . g
Intuitively, the Functor instance here allows you to apply f :: a -> b to the return value of a function g :: r -> a "before" (so to speak) you apply g to some x :: r. So for example, if this is the function that returns the length of its argument:
length :: [a] -> Int
...then this is the function that returns twice the length of its argument:
twiceTheLength :: [a] -> Int
twiceTheLength = fmap (*2) length
Useful fact: the Reader monad is just a newtype for (->):
newtype Reader r a = Reader { runReader :: r -> a }
instance Functor (Reader r) where
fmap f (Reader g) = Reader (f . g)
instance Applicative (Reader r) where
pure a = Reader (const a)
Reader f <*> Reader a = Reader $ \r -> f r (a r)
instance Monad (Reader r) where
return = pure
Reader f >>= g = Reader $ \r -> runReader g (f r) r
Now that we have that non-example out of the way, here's a type that can't be made into a Functor:
type Redaer a r = Redaer { runRedaer :: r -> a }
-- Not gonna work!
instance Functor (Redaer a) where
fmap f (Redaer g) = ...
Yep, all I did is spell the name backwards, and more importantly, flip the order of the type parameters. I'll let you try and figure out why this type can't be made an instance of Functor.

Functor is for (a -> b) -> (f a -> f b), what is for (Category c) => c a b -> c (f a) (f b)?

I would like to have a function for either mapping a pure function to a container or sequencing applicative/monadic action through it. For pure mapping we have
fmap :: Functor f => (a -> b) -> (f a -> f b)
For monadic sequencing we have (from Data.Taversable)
mapM :: (Traversable f, Monad m) => (a -> m b) -> (f a -> m (f b))
Which is similar to
mapKleisli :: (Traversable f, Monad m) => Kleisli m a b -> Kleisli m (f a) (f b)
mapKleisli = Kleisli . mapM . runKleisli
We know both (->) and (Kleisli m) are categories (and arrows). So it's naturally to make a generalization:
mapCategory :: (X f, Category c) => c a b -> c (f a) (f b)
Do you know such a class X with similar method? Maybe, somewhere on hackage? I tried to hoogle/hayoo but haven't found anything appropriate.
Update:
Now I know better what I need. Both Kleisli arrows and (->) are instances of ArrowApply which is as powerful as Monad. I came up with this arrow-based version of Travesable:
{-# LANGUAGE TypeOperators #-}
import Prelude hiding (id, (.), mapM)
import Control.Arrow
import Control.Category
class Traversable f where
traverse :: ArrowApply (~>) => f a -> (a ~> b) ~> f b
mapArrow :: (ArrowApply (~>), Traversable f) => a ~> b -> f a ~> f b
mapArrow a = arr (\x -> (traverse x, a)) >>> app
instance Traversable Maybe where
traverse Nothing = arr (const Nothing)
traverse (Just x) = arr (\a -> (a, x)) >>> app >>> arr Just
instance Traversable [] where
traverse [] = arr (const [])
traverse (x : xs) = undefined -- this is hard!
I could use just usual Applicative-based Traversable, with Identity for pure functions, but I'm not sure it is good. Considering pure functions as special case of monadic actions is weird. Interpreting both pure functions and monadic actions as instances of some action class (Category/Arrow/ArrowApply) looks more straightforward to me.
Questions: would you like to finish instance for []? Has my opinion about ArrowApply vs Monad any sense?
You're asking for "some class X", but it should be pretty clear that the most (or perhaps, only) correct name for this class would be "Functor". What you want is simply a functor class defined for an arbitrary Category instance, rather than limited to (->).
Of course, your definition is still limited to (endo)functors from a category to a subcategory defined by the type constructor giving the instance. If you generalize a bit further, there's no reason for the two categories to be the same, giving you a type class something like this one:
class (Category r, Category t) => Functor f r t | f r -> t, f t -> r where
fmap :: r a b -> t (f a) (f b)
This is still awfully limited vs. the full concept of a functor in category theory, but oh well.
It's also interesting to observe that this still has a (->) type constructor in it--that's because, even though we're modeling the source and target categories with arbitrary instances, the whole thing (and in particular, the functor itself) still exists in some sense in Hask, i.e., the category associated with (->). The other half of the functor (the part mapping objects) is, roughly speaking, the (->) in the kind * -> * for the type constructor f.

Making (a, a) a Functor

How can I make (a, a) a Functor without resorting to a newtype?
Basically I want it to work like this:
instance Functor (a, a) where
fmap f (x, y) = (f x, f y)
But of course that's not a legal way to express it:
Kind mis-match
The first argument of `Functor' should have kind `* -> *',
but `(a, a)' has kind `*'
In the instance declaration for `Functor (a, a)'
What I really want is a type-level function like this: \a -> (a, a) (invalid syntax). So a type alias, perhaps?
type V2 a = (a, a)
instance Functor V2 where
fmap f (x, y) = (f x, f y)
I would think this would work, but it doesn't. First I get this complaint:
Illegal instance declaration for `Functor V2'
(All instance types must be of the form (T t1 ... tn)
where T is not a synonym.
Use -XTypeSynonymInstances if you want to disable this.)
In the instance declaration for `Functor V2'
If I follow the advice and add the TypeSynonymInstances extension, I get a new error:
Type synonym `V2' should have 1 argument, but has been given 0
In the instance declaration for `Functor V2'
Well, duh, that's the point! V2 has kind * -> * which is what is required of a Functor instance. Well, ok, I can use a newtype like this:
newtype V2 a = V2 (a, a)
instance Functor V2 where
fmap f (V2 (x, y)) = V2 (f x, f y)
But now I've got to sprinkle V2s liberally throughout my code instead of just being able to deal with simple tuples, which kind of defeats the point of making it a Functor; at that point I might as well make my own function vmap :: (a -> b) -> (a, a) -> (b, b).
So is there any way to do this nicely, i.e. without a newtype?
As others have stated, there's no way to do this without resorting to newtypes or data declarations. However, have you looked at Control.Arrow? Many of those functions are very useful with tuples, for example:
vmap :: (a -> b) -> (a,a) -> (b,b)
vmap f = f *** f
You can declare
instance Functor ((,) a) where
...
However that doesn't constrain the first element of your pair, and fmap would only act on the second element.
The issue is that a tuple doesn't enforce a relationship between the types of the two elements.
If you don't want a newtype decorator you can make your own fresh type:
data Pair a = P a a
instance Functor Pair where
...
which will be easier to work with than a newtype around a tuple.
With singletons you can define a Functor type class for defunctionalized symbols (Type ~> Type instead of Type -> Type)
{-# Language ExplicitNamespaces, TypeApplications, TypeOperators, KindSignatures, ScopedTypeVariables, DataKinds, TypeInType, TypeFamilies, AllowAmbiguousTypes, InstanceSigs #-}
import Data.Kind (Type)
import Data.Singletons (type (~>), Apply)
class Functor' (f :: Type ~> Type) where
fmap' :: (a -> a') -> (Apply f a -> Apply f a')
data Dup :: Type ~> Type
type instance Dup `Apply` a = (a, a)
instance Functor' Dup where
fmap' :: (a -> a') -> ((a, a) -> (a', a'))
fmap' f (a1, a2) = (f a1, f a2)
This gives you a Prelude.Functor instance automatically
newtype f $ a = App (Apply f a)
instance Functor' f => Functor (($) f) where
fmap :: (a -> a') -> (f $ a -> f $ a')
fmap f (App fa) = App (fmap' #f f fa)

Resources