In the Functor class definition we have the <$ function defined as:
class Functor f where
fmap :: (a -> b) -> f a -> f b
(<$) :: a -> f b -> f a
(<$) = fmap . const
The const function has the definition:
const :: a -> b -> a
const x _ = x
I know that the <$ function is equivalent to:
\x -> fmap (const x)
How does fmap . const equate to the lambda expression above? My understanding of function composition is that output type of const should match the input type of fmap, but the input type of fmap is the function (a -> b) not a which is what the const function outputs.
Note that:
(f . g) x = f (g x)
(see the definition of (.)) so,
(fmap . const) x = fmap (const x)
Original Answer
For concreteness, let's use the IO functor.
fmap f work on an IO-computation by applying f to the result of the computation.
E.g. - getContents is an IO String, and length is a function on Strings, so we can fmap length on getContents:
getContents :: IO String
length :: String -> Int
fmap length getContents :: IO Int
When run this would read all of standard input, take the length of the input, and return it (as an IO-action).
Now, const z is a function which ignores its argument and always returns z. So if I were to fmap (const 'w') on getContents I would have:
getContents :: IO String
const 'w' :: String -> Char
fmap (const 'w') getContents :: IO Char
When executed, this would first read in all of standard input, then discard that input and return the character 'w'.
The other answer does a good job of addressing the question, "How does fmap . const equate to the lambda expression above?", so I want to address a different part:
My understanding of function composition is that output type of const should match the input type of fmap, but the input type of fmap is the function (a -> b) not a which is what the const function outputs.
In this answer, I will argue that the output type of const is indeed a function as needed by fmap.
Let's rewrite the types of fmap and const, using separate type variables in each to avoid confusion:
fmap :: Functor f => (a -> b) -> (f a -> f b)
const :: c -> (d -> c)
Now, one must ask: what is the output type of const? In your question, you posit that the output type is c (after correcting for type variable renaming as above). But in fact this is a slight misunderstanding; the true output type is d -> c!
The output of const is actually a function. Now, as you say, its output must match the input of fmap. With our naming above, this means we must choose to satisfy the equation d ~ a (read: type d and type a are the same type) and satisfy c ~ b. Then we will have:
const :: b -> (a -> b)
fmap :: (a -> b) -> (f a -> f b)
fmap . const :: b -> (f a -> f b)
Related
I am learning haskell currently and I am having a really hard time wrapping my head around how to explain <$> and <*>'s behavior.
For some context this all came from searching how to use an or operation when using takeWhile and the answer I found was this
takeWhile ((||) <$> isDigit <*> (=='.'))
In most of the documentation I have seen, <*> is used with a container type.
show <*> Maybe 10
By looking at
(<$>) :: Functor f => (a -> b) -> f a -> f b
It tells me that <*> keeps the outer container if its contents and applies the right to the inside, then wraps it back into the container
a b f a f b
([Int] -> String) -> [Just]([Int]) -> [Just]([String])
This makes sense to me, in my mind the f a is essentially happening inside the container, but when I try the same logic, I can make sense to me but I cant correlate the logic
f = (+) <$> (read)
so for f it becomes
a b f a f b
([Int] -> [Int -> Int]) -> ([String] -> [Int]) -> ([String] -> [Int -> Int])
So f being the container really confuses me when I try and work out what this code is going to do. I understand when I write it out like this, I can work it out and see its basically equivalent to the .
(.) :: (b -> c) -> (a -> b) -> a -> c
b c a b a c
([Int] -> [Int -> Int]) -> ([String] -> [Int]) -> ([String] -> [Int -> Int])
so it can be written as
f = (+) . read
Why not just write it as just that? Why wasn't the original snippet just written as
takeWhile ((||) . isDigit <*> (=='.'))
or does <$> imply something in this context that . des not?
Now looking at <*>, it seems like it is basicly exactly the same as the <$> except it takes two containers, uses the inner of both, then puts it pack in the container
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
so
Just show <*> Just 10
f a b f a f b
[Just]([Int->Int]->[Int]) -> [Just]([Int->Int]) -> [Just]([Int])
However with functions, it becomes murky how things are being passed around to each other.
Looking at the original snippit and breaking it up
f1 :: Char -> Bool -> Bool
f1 = (||) . isDigit
f2 :: Char -> Bool
f2 = f1 <*> (== '.')
<*> behavior in f2 is
f a b f a f b
([Char] -> [Bool] -> [Bool]) -> ([Char] -> [Bool]) -> ([Char] -> [Bool])
So using previous logic, I see it as Char -> is the container, but its not very useful for me when working out what's happening.
It looks to me as if <*> is passing the function parameter into right side, then passing the same function parameter, and the return value into the left?
So to me, it looks equivalent to
f2 :: Char -> Bool
f2 x = f1 x (x=='_')
Its a bit of mental gymnastics for me to work out where the data is flowing when I see <*> and <$>. I guess im just looking for how an experienced haskell-er would read these operations in their head.
The applicative instance for functions is quite simple:
f <*> g = \x -> f x (g x)
You can verify for yourself that the types match up. And as you said,
(<$>) = (.)
(Ignoring fixity)
So you can rewrite your function:
(||) <$> isDigit <*> (=='.')
(||) . isDigit <*> (=='.')
\x -> ((||) . isDigit) x ((=='.') x)
-- Which can simply be rewritten as:
\x -> isDigit x || x == '.'
But it's important to understand why the function instance is as it is and how it works. Let's begin with Maybe:
instance Applicative Maybe where
pure :: a -> Maybe a
pure x = Just x
(<*>) :: Maybe (a -> b) -> Maybe a -> Maybe b
Nothing <*> _ = Nothing
_ <*> Nothing = Nothing
(Just f) <*> (Just x) = Just (f x)
Ignore the implementation here and just look at the types. First, notice that we've made Maybe an instance of Applicative. What exactly is Maybe? You might say that it's a type, but that isn't true - I can't write something like
x :: Maybe
- that doesn't make sense. Instead, I need to write
x :: Maybe Int
-- Or
x :: Maybe Char
or any other type after Maybe. So we give Maybe a type like Int or Char, and it suddenly becomes a type itself! That's why Maybe is what's known as a type constructor.
And that's exactly what the Applicative typeclass expects - a type constructor, which you can put any other type inside. So, using your analogy, we can think of giving Applicative a container type.
Now, what do I mean by
a -> b
?
We can rewrite it using prefix notation (the same way 1 + 2 = (+) 1 2)
(->) a b
And here we see that the arrow (->) itself is also just a type constructor - but unlike Maybe, it takes two types. But Applicative only wants a type constructor which takes one type. So we give it this:
instance Applicative ((->) r)
Which means that for any r, (->) r is an Applicative. Continuing the container analogy, (->) r is now a container for any type b such that the resulting type is r -> b. What that means is that the contained type is actually the future result of the function on giving it an r.
Now for the actual instance:
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
Substituting (->) r as the applicative,
(<*>) :: ((->) r (a -> b)) -> ((->) r a) ((->) r b)
-- Rewriting it in infix notation:
(<*>) :: (r -> (a -> b)) -> (r -> a) -> (r -> b)
How would we go about writing the instance? Well, we need a way to get the contained type out of the container - but we can't use pattern matching like we did with Maybe. So, we use a lambda:
(f :: r -> (a -> b)) <*> (g :: r -> a) = \(x :: r) -> f x (g x)
And the type of f x (g x) is b, so the entire lambda has type r -> b, which is exactly what we were looking for!
EDIT: I noticed that I didn't talk about the implementation of pure for functions - I could update the answer, but try seeing if you can use the type signature to work it out yourself!
class Applicative f => Monad f where
return :: a -> f a
(>>=) :: f a -> (a -> f b) -> f b
(<*>) can be derived from pure and (>>=):
fs <*> as =
fs >>= (\f -> as >>= (\a -> pure (f a)))
For the line
fs >>= (\f -> as >>= (\a -> pure (f a)))
I am confused by the usage of >>=. I think it takes a functor f a and a function, then return another functor f b. But in this expression, I feel lost.
Lets start with the type we're implementing:
(<*>) :: Monad f => f (a -> b) -> f a -> f b
(The normal type of <*> of course has an Applicative constraint, but here we're trying to use Monad to implement Applicative)
So in fs <*> as = _, fs is an "f of functions" (f (a -> b)), and as is an "f of as".
We'll start by binding fs:
(<*>) :: Monad f => f ( a -> b) -> f a -> f b
fs <*> as
= fs >>= _
If you actually compile that, GHC will tell us what type the hole (_) has:
foo.hs:4:12: warning: [-Wtyped-holes]
• Found hole: _ :: (a -> b) -> f b
Where: ‘a’, ‘f’, ‘b’ are rigid type variables bound by
the type signature for:
(Main.<*>) :: forall (f :: * -> *) a b.
Monad f =>
f (a -> b) -> f a -> f b
at foo.hs:2:1-45
That makes sense. Monad's >>= takes an f a on the left and a function a -> f b on the right, so by binding an f (a -> b) on the left the function on the right gets to receive an (a -> b) function "extracted" from fs. And provided we can write a function that can use that to return an f b, then the whole bind expression will return the f b we need to meet the type signature for <*>.
So it'll look like:
(<*>) :: Monad f => f ( a -> b) -> f a -> f b
fs <*> as
= fs >>= (\f -> _)
What can we do there? We've got f :: a -> b, and we've still got as :: f a, and we need to make an f b. If you're used to Functor that's obvious; just fmap f as. Monad implies Functor, so this does in fact work:
(<*>) :: Monad f => f ( a -> b) -> f a -> f b
fs <*> as
= fs >>= (\f -> fmap f as)
It's also, I think, a much easier way to understand the way Applicative can be implemented generically using the facilities from Monad.
So why is your example written using another >>= and pure instead of just fmap? It's kind of harkening back to the days when Monad did not have Applicative and Functor as superclasses. Monad always "morally" implied both of these (since you can implement Applicative and Functor using only the features of Monad), but Haskell didn't always require there to be these instances, which leads to books, tutorials, blog posts, etc explaining how to implement these using only Monad. The example line given is simply inlining the definition of fmap in terms of >>= and pure (return)1.
I'll continue to unpack as if we didn't have fmap, so that it leads to the version you're confused by.
If we're not going to use fmap to combine f :: a -> b and as :: f a, then we'll need to bind as so that we have an expression of type a to apply f to:
(<*>) :: Monad f => f ( a -> b) -> f a -> f b
fs <*> as
= fs >>= (\f -> as >>= (\a -> _))
Inside that hole we need to make an f b, and we have f :: a -> b and a :: a. f a gives us a b, so we'll need to call pure to turn that into an f b:
(<*>) :: Monad f => f ( a -> b) -> f a -> f b
fs <*> as
= fs >>= (\f -> as >>= (\a -> pure (f a)))
So that's what this line is doing.
Binding fs :: f (a -> b) to get access to an f :: a -> b
Inside the function that has access to f it's binding as to get access to a :: a
Inside the function that has access to a (which is still inside the function that has access to f as well), call f a to make a b, and call pure on the result to make it an f b
1 You can implement fmap using >>= and pure as fmap f xs = xs >>= (\x -> pure (f x)), which is also fmap f xs = xs >>= pure . f. Hopefully you can see that the inner bind of your example is simply inlining the first version.
Applicative is a Functor. Monad is also a Functor. We can see the "Functorial" values as standing for computations of their "contained" ⁄ produced pure values (like IO a, Maybe a, [] a, etc.), as being the allegories of ⁄ metaphors for the various kinds of computations.
Functors describe ⁄ denote notions ⁄ types of computations, and Functorial values are reified computations which are "run" ⁄ interpreted in a separate step which is thus akin to that famous additional indirection step by adding which, allegedly, any computational problem can be solved.
Both fs and as are your Functorial values, and bind ((>>=), or in do notation <-) "gets" the carried values "in" the functor. Bind though belongs to Monad.
What we can implement in Monad with (using return as just a synonym for pure)
do { f <- fs ; -- fs >>= ( \ f -> -- fs :: F (a -> b) -- f :: a -> b
a <- as ; -- as >>= ( \ a -> -- as :: F a -- a :: a
return (f a) -- return (f a) ) ) -- f a :: b
} -- :: F b
( or, with MonadComprehensions,
[ f a | f <- fs, a <- as ]
), we get from the Applicative's <*> which expresses the same computation combination, but without the full power of Monad. The difference is, with Applicative as is not dependent on the value f there, "produced by" the computation denoted by fs. Monadic Functors allow such dependency, with
[ bar x y | x <- xs, y <- foo x ]
but Applicative Functors forbid it.
With Applicative all the "computations" (like fs or as) must be known "in advance"; with Monad they can be calculated -- purely -- based on the results of the previous "computation steps" (like foo x is doing: for (each) value x that the computation xs will produce, new computation foo x will be (purely) calculated, the computation that will produce (some) y(s) in its turn).
If you want to see how the types are aligned in the >>= expressions, here's your expression with its subexpressions named, so they can be annotated with their types,
exp = fs >>= g -- fs >>=
where g f = xs >>= h -- (\ f -> xs >>=
where h x = return (f x) -- ( \ x -> pure (f x) ) )
x :: a
f :: a -> b
f x :: b
return (f x) :: F b
h :: a -> F b -- (>>=) :: F a -> (a -> F b) -> F b
xs :: F a -- xs h
-- <-----
xs >>= h :: F b
g f :: F b
g :: (a -> b) -> F b -- (>>=) :: F (a->b) -> ((a->b) -> F b) -> F b
fs :: F (a -> b) -- fs g
-- <----------
fs >>= g :: F b
exp :: F b
and the types of the two (>>=) applications fit:
(fs :: F (a -> b)) >>= (g :: (a -> b) -> F b)) :: F b
(xs :: F a ) >>= (h :: (a -> F b)) :: F b
Thus, the overall type is indeed
foo :: F (a -> b) -> F a -> F b
foo fs xs = fs >>= g -- foo = (<*>)
where g f = xs >>= h
where h x = return (f x)
In the end, we can see monadic bind as an implementation of do, and treat the do notation
do {
abstractly, axiomatically, as consisting of the lines of the form
a <- F a ;
b <- F b ;
......
n <- F n ;
return (foo a b .... n)
}
(with a, F b, etc. denoting values of the corresponding types), such that it describes the overall combined computation of the type F t, where foo :: a -> b -> ... -> n -> t. And when none of the <-'s right-hand side's expressions is dependent on no preceding left-hand side's variable, it's not essentially Monadic, but just an Applicative computation that this do block is describing.
Because of the Monad laws it is enough to define the meaning of do blocks with just two <- lines. For Functors, just one <- line is allowed ( fmap f xs = do { x <- xs; return (f x) }).
Thus, Functors/Applicative Functors/Monads are EDSLs, embedded domain-specific languages, because the computation-descriptions are themselves values of our language (those to the right of the arrows in do notation).
Lastly, a types mandala for you:
T a
T (a -> b)
(a -> T b)
-------------------
T (T b)
-------------------
T b
This contains three in one:
F a A a M a
a -> b A (a -> b) a -> M b
-------------- -------------- -----------------
F b A b M b
You can define (<*>) in terms of (>>=) and return because all monads are applicative functors. You can read more about this in the Functor-Applicative-Monad Proposal. In particular, pure = return and (<*>) = ap is the shortest way to achieve an Applicative definition given an existing Monad definition.
See the type signatures for (<*>), ap and (>>=):
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
ap :: Monad m => m (a -> b) -> m a -> m b
(>>=) :: Monad m => m a -> (a -> m b) -> m b
The type signature for (<*>) and ap are nearly equivalent. Since ap is written using do-notation, it is equivalent to some use of (>>=). I'm not sure this helps, but I find the definition of ap readable. Here's a rewrite:
ap m1 m2 = do { x1 <- m1; x2 <- m2; return (x1 x2) }
≡ ap m1 m2 = do
x1 <- m1
x2 <- m2
return (x1 x2)
≡ ap m1 m2 =
m1 >>= \x1 ->
m2 >>= \x2 ->
return (x1 x2)
≡ ap m1 m2 = m1 >>= \x1 -> m2 >>= \x2 -> return (x1 x2)
≡ ap mf ma = mf >>= (\f -> ma >>= (\a -> pure (f a)))
Which is your definition. You could show that this definition upholds the applicative functor laws, since not everything defined in terms of (>>=) and return does that.
I am learning haskell and one of the tricky part are type variables.
Consider following example:
Prelude> :t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
there is type variables a and b, they can be any type. And f is a type that has to be implemented a Functor.
Lets define a function for first argument for fmap:
Prelude> let replaceWithP = const 'p'
Now, I pass the function replaceWithP to fmap and looking at the type signature:
Prelude> :t fmap replaceWithP
fmap replaceWithP :: Functor f => f b -> f Char
Why does f a becomes to f b, why does it not stay a?
First, the type
fmap replaceWithP :: Functor f => f b -> f Char
is exactly equivalent to
fmap replaceWithP :: Functor f => f a -> f Char
because all type variables are implicitly universally quantified, so they can be renamed at will (this is known as alpha-conversion).
One might still wonder where the name b printed by GHC comes from. After all, fmap had f a in its type, so why did GHC choose to rename it as b?
The "culprit" here is replaceWithP
> :t const
const :: a -> b -> a
> let replaceWithP = const 'p'
> :t replaceWithP
replaceWithP :: b -> Char
So, b comes from the type of replaceWithP.
Type variables can be thought of normal variables, except you have types instead.
What does this mean? For instance, the variable a in C might be defined as:
int a = 2;
What are the possible values that you could have assigned a? The whole int range, because that's the set of values that a may take on. Let's take a look at this in pseudo-Haskell:
type b = Int
What are the set of values that b may take on? That's a trickier question. Typically we're used to seeing things such as 2, "hello", or True as values. However, in Haskell, we also allow types to be treated as values. Sort of. Let's say that b can take on any kind of form *. Essentially, this includes all types that do not need extra information for their construction:
data Tree a = Leaf a | Branch (Tree a) (Tree a)
Tree -- no, has kind: * -> *
Tree Int -- okay!
Int -- okay!
String -- okay!
This means that in your example:
fmap :: Functor f => (a -> b) -> f a -> f b
The variables a and b can be thought of variables that can take on types of any form provided that the type you decide to give it is within the appropriate range of type values (as restricted by kinds).
To more precisely answer your question now: why do we observe that:
fmap :: Functor f => (a -> b) -> f a -> f b
fmap replaceWithP :: Functor f => f b -> f Char
Let me rewrite the following equivalent definition, because variable naming can cause confusion:
fmap :: Functor f => (a -> b) -> f a -> f b
fmap replaceWithP :: Functor f => f z -> f Char
Hopefully this looks more clear now. When you supplied the replaceWithP :: x -> Char function, the following mappings occur:
-- Function types
fmap :: Functor f => (a -> b) -> f a -> f b
replaceWithP :: x -> Char
-- Type variable mappings
a -> x
b -> Char
What does this look like if we perform substitution?
Functor f => (x -> Char) -> f x -> f Char
After you have supplied in the replaceWithP function, you consume the first parameter, so you're left with:
fmap replaceWithP :: Functor f => f x -> f Char
Or equivalently:
fmap replaceWithP :: Functor f => f b -> f Char
Haskell newbie here.
So (<$>) is defined as
(<$>) :: Functor f => (a -> b) -> f a -> f b
And (<*>) is defined as
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
But I feel like Applicative is two concepts in one:
One would be that of a functor
And one would be this:
(<#>) :: MyConcept m => m (a -> b) -> a -> b
So e.g. thinking in terms of Maybe:
I have an let i = 4 and I have a let foo = Nothing :: Num a => Maybe (a -> a).
Basically I have a function that may or may not be there, that takes an Int and returns an Int, and an actual Int.
Of course I could just wrap i by saying:
foo <*> Just i
But that requires me to know the what Applicative foo is wrapped in.
Is there something equivalent to what I described here? How would I go about implementing that function <#> myself?
It would be something like this:
let (<#>) func i = func <*> ??? i
You can use pure:
pure :: Applicative f => a -> f a
foo <*> pure i
although you could just use fmap:
fmap (\f -> f i) foo
or
fmap ($ i) foo
(<#>) :: MyConcept m => m (a -> b) -> a -> b
To see if this is like an Applicative try deriving <#> from <*> and pure. You will find that it is impossible.
Where you can find <#> in a more general form is extract :: (Counit w) => w a -> a for comonads.
Can you implement extract for Maybe? What do you do when the value is Nothing?
I'm trying to understand some code and I'm getting myself tangled fairly well. Please help me to understand my logic, or lack thereof ...
To start:
*Main> :t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
If I just want f a to be a function that takes one parameter, it's okay and makes sense:
*Main> :t \f -> fmap f (undefined :: String -> Int)
\f -> fmap f (undefined :: String -> Int) :: (Int -> b) -> String -> b
I can pass in a String in the second param, which generates an Int, and then use the function in the first param to generate the b.
Now, I want f a to be a function that takes two parameters, so I substitute that in:
*Main> :t \f -> fmap f (undefined :: String -> Int -> Bool)
\f -> fmap f (undefined :: String -> Int -> Bool)
:: ((Int -> Bool) -> b) -> String -> b
At this point, I'm confused. I already provided the function that converts from the String and the Int into the Bool. How can I now provide another function that takes a Int -> Bool to convert into a b? Is this non-sensical or am I not reading this right?
Or maybe this is a case of a functor within a functor and more needs to be done to make this make sense? In which case, what?
There is actually no such thing as a function with two parameters in Haskell. Every function has exactly one parameter.
In particular, String -> Int -> Bool is a function which accepts one String parameter. (Of course, knowing that the result is again a function you are able to use it as if it were a function with two parameters.) So if you want to unify this with f a, you need
f ~ (String->)
a ~ Int->Bool
Indeed Int->Bool can itself be interpreted as a functor-application†
f ~ (String->)
g ~ (Int->)
b ~ Bool
so that String->Int->Bool ~ f (g b); thus
\f -> fmap (fmap f) (undefined :: String -> Int -> Bool)
:: (Bool -> b) -> String -> Int -> b
I don't think the function family of functors is really a good example for grasping properties of functors/applicatives/monads. List and maybes are generally much less confusing; instead of the plain function functor the equivalent Reader is preferred when you need that functionality (pun not intended).
Regarding your original expression, that is actually not meaningless. If we translate it to a tamer functor, we could for instance write
> fmap ($2) [(>1), (>2), (>3)]
[True, False, False]
Much the same thing can be done with the function functor:
> fmap ($2) (<) 1
True
> fmap ($2) (<) 2
False
> fmap ($2) (<) 3
False
Of course that example is a bit too simple to be useful, but you can also implement nontrivial ones.
†Note that f and g are actually not the same functor. We tend to call them both “the function functor”, but really you get a different functor for every partial application of the (->) constructor. That means, you can't in any way unify the two layers, even though there's a Monad (a->) instance.