Learn you a haskell gives description about Functor typeclass.
I can see that for list, it's implemented as follows:
instance Functor [] where
fmap = map
But how does this work ?
In the typeclass Functor, fmap doesn't even have an implementation. All it has is just type declaration like this:
class Functor f where
fmap :: (a -> b) -> f a -> f b
Just by having the type declaration, how does Haskell figure out map operation for Lists correctly ?
map is just a normal function with type (a -> b) -> [a] -> [b]. Unlike fmap, it is not part of the Functor typeclass. It works exactly how you think it does.
The idea behind typeclasses is that you use the types to figure out which implementation to use. When we say instance Functor [] where ..., we're telling the compiler what the implementation of fmap for [] (the list type) is.
In this case, the implementation for fmap is just map, which is a normal function.
Related
Spin off of this question. Intuitively I have understood what sequenceA does in that usecase, but not how/why it works like that.
So it all boils down to this question: how does sequenceA work in the following case?
> sequenceA [("a",1),("b",2),("c",3)]
("abc",[1,2,3])
I see that
sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)
so in the usecase above the Traversable is [], and the Applicative, since (,) is a binary type constructor, is (,) a, which means that the pair is taken as an applicative functor on its snd field. And this goes together the list ending up in the snd of the result. So we go from a list of pairs to a pair with a list in its second field.
But where does the "abc" come from? I mean, I know that it's the concatenation of the fst of all the pairs, but I don't know if it's via ++ or via concat of the list of the fsts. There seems to be nothing in sequenceA's signature to enforce that the fsts of the pairs can be combined together.
Still that assumption has to be used somewhere. Indeed, the following fails
sequenceA [('a',1),('b',2),('c',3)]
It uses mappend. The Applicative instance it uses looks like this:
instance Monoid a => Applicative ((,) a) where
pure x = (mempty, x)
(af, f) <*> (ax, x) = (mappend af ax, f x)
In Haskell, typeclass instances for a type can be "conditional" on the existence of other typeclass instances for parts of the type. Not all type constructors
of the form ((,) a)are instances of Applicative, but only those for which the a type has a Monoid instance.
These required constraints appear before the => in the instance's Haddocks, like this:
Monoid a => Applicative ((,) a)
Why is the Monoid instance required? For one, pure for ((,) a) needs to materialize an a value out of thin air to put in the first element of the tuple. mempty for the type a does the job.
There can be chains of required constraints that are several levels deep. For example, why does the following work?
ghci> import Datta.Function ((&)) -- flipped application
ghci> [(id :: String -> String, 2 :: Int), (\x -> x ++ x, 1)] & sequenceA & fst $ "foo"
"foofoofoo"
Here the first component is a function. As before, it must have a Monoid instance for the sequenceA to work. But when is the type a -> b a Monoid? Looking at the Haddocks, we find:
Monoid b => Monoid (a -> b)
That is, functions are Monoids when the return type (here String) is a Monoid.
Actually, there's another Monoid instance for functions available through the Endo newtype. It's common to use newtypes to select which instance to use for a given operation, although it requires some amount of wrapping and unwrapping.
I have a data type:
data Tree a = Leaf | Branch a (Tree a) (Tree a)
I want to determine, and not just for this data type, but for others such as String, if these data types are law-abiding instances of functor (https://hackage.haskell.org/package/base-4.14.0.0/docs/Data-Functor.html). The link indicates that you can prove a type is a functor if it has a function fmap, which, given any types a and b, lets you apply any function of type (a -> b) to turn an f a into an f b, preserving the structure of f. How would I test this for my Tree data type, or String data type?
Short non-answer
Before you do any thinking yourself, try to let GHC write the instance for you:
{-# LANGUAGE DeriveFunctor #-}
data Tree a = Leaf | Branch a (Tree a) (Tree a)
deriving (Functor)
This happens to work in this case, and then you're guaranteed to have a law-abiding instance!
Seriously, this is the way you should typically acquire Functor instances for your data types. But you should still know yourself when it makes sense!
Actual Answer
I want to determine, and not just for this data type, but for others such as String, if these data types are law-abiding instances of Functor
So, for a Functor instance, you first of all need a parametric type, i.e. a “container” that doesn't care what type you store in it. So, strictly speaking the functor shouldn't be a type at all but a type constructor or type-level function★. Practically speaking, you see that by checking if the data declaration has type variables: in case of Tree you immediately see it in your code
data Tree a = ... ✓
If you don't have the source code handy, you can ask GHCi for the kind:
Prelude> :set -XTypeInType -XNoStarIsType†
Prelude> :k Maybe
Maybe :: Type -> Type ✓
Prelude> :k String
String :: Type ✗
As you see, String does not even have a type parameter, so it can't possibly be a functor.‡
Next, you need to look how the type variable is used in the data structure. If there are multiple type parameters, all of the following applies to the last (rightmost) of them, e.g. in data Either a b = ... we'd be talking about the b parameter.
If it's not used at all (i.e. if it's a phantom type argument) then you can trivially write a law-abiding Functor instance: just don't use the mapping-function either.
data Tough a = Tough String
instance Functor Tough where
fmap _ (Tough s) = Tough s
(However perhaps you shouldn't write a functor instance in this case, because phantom arguments are often meant to be constant unique tags.)
If it's used directly as part of one of fields in a type constructor, then you can write a functor instance. The fmap-ped function should then be applied to all those values.
data Maybe a = Nothing
| Just a
instance Functor Maybe where
fmap _ Nothing = Nothing
fmap f (Just a) = Just $ f a
If it's used somewhere deeper nested in the data structure, but all the nesting is in functors itself, then it's a functor. (This also holds up if it's the same functor you're just trying to define yourself, i.e. for recursive types!)
data TwoLists a = TwoLists {listL :: [a], listR :: [a]}
instance Functor TwoLists where
fmap f (TwoLists ll lr) = TwoLists (fmap f ll) (fmap f lr)
[Advanced, probably best if you ignore this for now] if the nesting consists of not normal (covariant) functors, but of an even number of contravariant functors, then your whole type is also a covariant functor.
★Type constructors are actually a very specific sort of type-level function, in particular they're injective. Mathematically speaking, a functor doesn't need to map its objects injectively (in case of Hask, the objects are types), but in Haskell this is necessary for the type checker.
†These syntactic extensions cause GHCi to show the kind of types as Type; historically it would show * instead and that's still the default in older GHC version, but now deprecated.
‡However, String is actually a synonym for [Char] i.e. a list of characters, and list is a functor. So you can actually perform fmap over a string, but that doesn't mean your using the “string functor”: you're using the list functor, and even if you started with a string the result may not be a string (but e.g. a list of integers).
Try to write such a function. If you succeed, it is definitely a Functor. If you fail, it might not be, or maybe you are not creative enough1. For Tree, it is relatively straightforward to implement, though of course a beginner may need to ask for help.
Specializing the signature of fmap to your Tree, you want a function with this signature:
mapTree :: (a -> b) -> Tree a -> Tree b
mapTree f Leaf = _
mapTree f (Branch value left right) = _
1 Actually there are many types that you can prove are not Functors just by looking at the fields of their constructors, but since that doesn't apply to Tree we won't get into it.
Warning: this is incomplete; I'm hoping someone can fill the hole I left regarding the functoriality of fixed points. Fact 5 and my use of it feel shaky.
String is not a functor, because it has the wrong kind. String :: Type, but a functor has to have kind Type -> Type.
Before we talk about Tree, let's establish a few facts.
Constant a (for any type a) is a functor:
-- From Data.Functor.Constant
newtype Constant a b = Constant { getConstant :: a }
instance Functor (Constant a) where
fmap _ (Constant x) = Constant x
Identity is a functor
-- Adapted from Data.Functor.Identity
newtype Identity a = Identity { runIdentity :: a }
instance Functor Identity where
fmap f (Identity x) = Identity (f x)
Sum types are functors, if the components are functors.
-- From Data.Functor.Sum
data Sum f g a = InL (f a) | InR (g a)
instance (Functor f, Functor g) => Functor (Sum f g) where
fmap f (InL x) = InL (fmap f x)
fmap f (InR y) = InR (fmap f y)
Product types are functors, if the components are functors
-- From Data.Functor.Product
data Product f g a = Pair (f a) (g a)
instance (Functor f, Functor g) => Functor (Product f g) where
fmap f (Pair x y) = Pair (fmap f x) (fmap f y)
Certain fixed points are functors.
-- From Data.Functor.Fixedpoint
newtype Fix f = Fix { unFix :: f (Fix f) }
instance (Functor f, Functor t) => Functor (Fix (f t)) where
fmap g (Fix h) = Fix (fmap g (unfix h))
With these facts in mind, we will decompose our Tree type into a combination of sums and products of known functors, which will thus establish that our type is isomorphic to a functor, and therefore a functor itself.
First, Leaf is just a descriptive alias for (), and we can replace the recursive reference to Tree a with another type parameter.
-- This is slightly different from some explanations of
-- recursive types, where t would be the subtree type itself, not
-- a type constructor.
data TreeF t a = () | Branch a (t a) (t a)
Next, we get rid of a by noticing that the type () is isomorphic to Constant () a and a is isomorphic to Identity a. Further, a three-way product is isomorphic to two two-way products (i.e., (a, b, c) ~ (a, (b, c))):
-- Algebraically, T a = 1 + a*T*T
data TreeF t = Sum (Constant ()) (Product Identity (Product t t))
Facts 1-4 above allow us to conclude that TreeF t is a functor whenever t is a functor.
Finally, we can use "fact" 5 to conclude that Fix TreeF (Fix TreeF) ~ Tree is a functor.
The type of map is: (a->b) -> [a] -> [b]
while the type of the functor fmap is:
Functor f => (a+b) -> f a -> f b
I read on wikipedia that map was a polymorphic morphism while fmap was a polytypic morphism but that doesn't really clear up things for me.
So my question is: is the map function a functor?
In Haskell terms, fmap is a method in the typeclass Functor, not the functor itself. [], Maybe, ... are type constructors which instantiates the class Functor and, abusing the language, you can say that "Maybe is a functor".
In mathematical terms, a functor (or more specifically in this case, an endofunctor in the category Hask, the category of Haskell types) is composed of two mappings: the first one from a type to another and the second from an arrow (a -> b) to another (f a -> f b) which preserves the structure. In that sense, Maybe is the first arrow which maps a type to another, say Int to Maybe Int and the fmap for Maybe is the second arrow.
No, but any container that implements fmap is a functor. Lists implement fmap as well (give it a try!), so lists are functors. Map is just the implementation of fmap for lists.
Like all (->) r types map is also a functor.
(->) r is actually just a simple function type like r -> a and all functions are functors. Like other functors you may think a function like a container but you get the contained value when you apply a value. However as for a Functor instance we can not have a type with two type variables. That's why we partially apply it. Just like Either a b is done like instance Functor (Either a). Since we are interested in the return value of a function the Functor instance of a function type is a partially applied r -> a which is (->) r.
So lets see a functions Functor instance.
instance Functor ((->) r) where
fmap f g = (\x -> f (g x))
So coming back to the question, map is a function with type (a -> b) -> [a] -> [b] and we can rewrite this like (a -> b) -> ([a] -> [b]) so here r variable in the Functor instance stands for a -> b and a variable in the Functor instance stands for [a] -> [b]. So lets apply fmap on map like fmap ($) map. Which essentially means it will return us a function like \x -> ($) map x. Where x has to be a (a -> b) type function. So lets use <$>; the infix representation of fmap in the below example ;
Prelude> (($) <$> map) (+2) [1,2,3]
[3,4,5]
So.. yes map is a functor.
Why does the type class Functor have only the memberfmap? I often find it useful to perform a fold over datatypes. Say, hierarchical ones, like a tree.
Note that a map is a special case of fold, that is, the latter is more fundamental. I guess I can take it the way it is, but maybe there is a reason?
Because a Functor is a very general kind of object; not all Functors support folds. For example, there is an instance1
instance Functor (a ->) where
-- > fmap :: (b -> c) -> (a -> b) -> (a -> c)
fmap f g = g . f
But, while (a ->) is a Functor for all a, for infinite a there isn't a reasonable fold definition. (Incidentally, a 'fold' in general is a catamorphism, which means it has a different type for each functor. The Foldable type class defines it for sequence-like types.).
Consider what the foldr definition for Integer -> Integer would look like; what would the outermost application be? What would the value of
foldr (\ _ n -> 1 + n) 0 (\ n -> n + 1)
be? There isn't a reasonable definition of fold without a lot more structure on the argument type.
1 (a ->) isn't legal Haskell for some reason. But I'm going to use it anyway as a more readable version of (->) a, since I think it's easier for a novice to understand.
The abstraction you are looking for is Foldable: This is a type class providing variuos forms of fold.
There is also Traversable for things where you can “fold while changing”, comparable to the mapAccumL function for lists.
It is actually not true that fmap is a special case of fold, as pointed out by #DietrichEpp, see as here are possible non-Functor instances of Foldable.
map is however a special case of mapAccumL (no surprise, given the name), and hence the definition of Traversable requires the thing to be also a Functor and a Foldable.
I know that fmap has type (a -> b) -> f a -> f b where f is a functor (and does different things depending on what the functor is). My basic question is this: given some invocation fmap r x, how does ghc figure out what the functor f is, just given the types of x and r?
Let me make this more precise. Suppose f and f' are functors such that f a = f' a for some type a, but f b and f' b are different. If r has type a -> b and x has type f a, it seems there are two different possible results for fmap r x: something of type f b and something of type f' b. How is this ambiguity resolved?
A secondary question: I wanted to test this out by making a weird functor -- maybe something that takes a to [Int] for any type a and does something stupid to functions... but I apparently haven't found the right bit of syntax that allows me to specify functors this way. (Is there something like data Newtype a = [Int] that works? It seems I'd need to make a typeclass name before I can make it an instance of functor.)
EDIT: I get it now, but for the record, the real issue (which is only implicit in my question) was that I didn't realize you can't have a functor Foo such that Foo a is a type like Int that already exists.
I think the general answer you're looking for is that Haskell types are organized using "kinds", which are like types of types.
Here's the Functor class
class Functor f where
fmap :: (a -> b) -> f a -> f b
It's not explicit, but this means that f is a type constructor with kind * -> *. Only types with that kind can be made Functors.
This is actually a rather strong statement. It means that any Functor must be parametric in a type argument. Now consider your statement:
Suppose f and f' are functors such that f a = f' a for some type a,
but f b and f' b are different.
Given the kind system, this isn't possible. Since a Functor is parametric in its type argument, f a = f' a implies f = f', therefore f b = f' b.
I'm not entirely sure what you're asking for with the "weird functor", but it sounds like something that couldn't be expressed with the Functor type class. IIRC Functor can only express endofunctors on Hask; you may need a different abstraction that allows for functors between categories.
Haskell type classes are based on first-order logic resolution. A type class constraint on a type variable is a predicate (you may have seen error messages indicating this if you ever tried to use a type class name where a type name was required) in that logic system.
Haskell requires a unique solution for each (Predicate, Type) pair throughout the program, so you will not be able to create two different Functor instances over Int, for example. The standard way around this, such as in the Monoid class for numeric types that could provide either a summation or product depending on how you define the monoidal operator you want to use, is to provide newtype wrappers over the concrete type that you want the class to have different instances for.
So, for Monoid, we have newtype Sum a = Sum { getSum :: a } and instance Num a => Monoid (Sum a) for the sum monoid and newtype Product a = Product { getProduct :: a } and instance Num a => Monoid (Product a) for the product monoid.
Note that since type only creates an alias for a type, it's not sufficient to provide multiple class instances for a type. The newtype declaration is like type in the sense that it does not produce any additional run-time structure for the new type, but it is unlike type in that it creates a new type rather than a type alias.
It depends on what argument you pass it. For example a list is a functor and so is Maybe
main = do
putStrLn $ show (double [1..5])
putStrLn $ show (double (Just 3))
putStrLn $ show (double Nothing)
double :: (Functor f, Num a) => f a -> f a
double = fmap (*2)
*Main> main
[2,4,6,8,10]
Just 6
Nothing
This double function will work for any functor that is holding an Num.
"Suppose f and f' are functors such that f a = f' a for some type a, but f b and f' b are different."
This doesn't really make sense. Either f and f' are the same, or they aren't. You seem to be suggesting some kind of in-between state where it varies depending on the argument type; that can't happen.
"If r has type a -> b and x has type f a, it seems there are two different possible results for fmap r x: something of type f b and something of type f' b. How is this ambiguity resolved?"
Where did f' come from? Nothing in the above signatures mentions it. Since x has type f a, it follows that the result of fmap must have some type beginning with f - in this case f b, since r :: a -> b. This is perfectly unambiguous. The result of fmap is always in the same functor as you started with.