This question is related to this answer.
There is a type named Promise:
data Promise f a = PendingPromise f | ResolvedPromise a | BrokenPromise deriving (Show)
It is stated that:
Promise f a ≅ Maybe (Either f a)
Now I cannot understand the above expression. How are they sort of
equivalent and isomorphic (and from that how can you conclude that it
is a Monad) ?
Two types A and B are isomorphic if there's two functions a2b :: A -> B and b2a :: B -> A such that a2b . b2a ≡ id and b2a . a2b ≡ id. In the example this is easy to prove: the two functions have basically the same clauses with the sides of = turned around, e.g.
promise2Trafo (PendingPromise f) = ErrorT . Just $ Left f
trafo2Promise (ErrorT (Just (Left f))) = PendingPromise f
so composing the functions in either order gives you the identity function. The crucial thing about an isomorphism is that a2b x ≡ a2b y holds exactly iff x ≡ y.
Now, how does that help proving typeclass laws? Again taken from the example,
instance Applicative Promise where
pure = trafo2Promise . pure
fp <*> xp = trafo2Promise $ promise2Trafo fp <*> promise2Trafo xp
Now here we need to prove amongst other things
pure id <*> xp ≡ xp
Instead of doing this by hand, we exploit the fact that this law has already been proven for ErrorT f Maybe a, so we simply introduce some identities:
trafo2Promise $ promise2Trafo (trafo2Promise $ pure id) <*> promise2Trafo xp
≡ trafo2Promise $ pure id <*> promise2Trafo xp
which is ≡ promise2Trafo xp iff pure id <*> promise2Trafo xp ≡ promise2Trafo xp, which we know is true.
A value of type Promise f a can be three different things:
A value of type f, with constructor PendingPromise.
A value of type a, with constructor ResolvedPromis,
or no value, with constructor BrokenPromise.
Similarly, a value of Maybe (Either f a) can be three things:
A value of type f, with 'constructor' Just . Left.
A value of type a, with 'constructor' Just . Right.
No value, with constructor Nothing.
So in that sense the types are isomorphic. The reason that this is not quite true in Haskell has to do with undefined values (bottoms), but you can ignore those to make life easier.
Maybe (Either f a) can also be seen as EitherT f (Maybe a), which is an instance of Monad.
You can easily map a Promise f a to a Maybe (Either f a) as follows:
PendingPromise f -> Just (Left f)
ResolvedPromise a -> Just (Right a)
BrokenPromise -> Nothing
Given that both Maybe and Either are instances of Monad, it is possible for Promise to be expressed as a monad.
A possible implementation could be:
instance Monad (Promise f) where
return a = ResolvedPromise a
BrokenPromise >>= _ = BrokenPromise
PendingPromise a >>= _ = PendingPromise a
ResolvedPromise a >>= f = f a
Live demo
There are three possiblilities for Maybe (Either f a):
Just (Left f) | Just (Right a) | Nothing
this is isomorphic to to Promise f a.
This is also the same as
EitherT f (Maybe a)
which is also a monad.
Related
In a recent assignment I have been asked to define fold functions for some non-list types. I'm still not quite able to wrap my head around this concept yet. Thus far, I have understood fold as performing over subsequent elements in the list. fold on Tree still do make intuitive sense, since one is able to apply some function recursively over the root's sub-trees.
However, on a datatype like:
Maybe a :: Nothing | Just a
There is no list (as it seems to me) to perform the fold action on.
I'm sure I have some issue with understanding the basic concepts here, and I would greatly appreciate some clearing up.
Foldable is a pretty confusing class, to be honest, because it doesn't have an awful lot of laws and it's quite possible to write quite a lot of different Foldable instances for almost any given type. Fortunately, it's possible to figure out what a Foldable instance should do in a purely mechanical way based on a Traversable instance for the same type—if there is one.
We have
class (Functor t, Foldable t) => Traversable t where
traverse :: Applicative f => (a -> f b) -> t a -> f (t b)
Traversable has several different laws, but it turns out the most important one is traverse Identity = Identity. Let's see how this applies to Maybe:
traverse :: Applicative f => (a -> f b) -> Maybe a -> f (Maybe b)
traverse g Nothing = _none
traverse g (Just a) = _some
Now in the first case, you need to produce f (Maybe b), and all you have is g :: a -> f b. Since you don't have any f values, and you don't have any a values, the only thing you can produce is pure Nothing.
In the second case, you have to produce f (Maybe b) and you have g :: a -> f b and a. So the only interesting way to start is to apply g to a, getting g a :: f b. Now you have two options to consider: you could throw away this value, and just return Nothing, or you can wrap it up in Just.
By the identity law, traverse Identity (Just a) = Identity (Just a). So you're not allowed to return Nothing. The only legal definition is
traverse _ Nothing = pure Nothing
traverse g (Just a) = Just <$> g a
The Traversable instance for Maybe is completely determined by the Traversable laws and parametricity.
Now it's possible to fold using traverse:
foldMapDefault :: (Traversable t, Monoid m)
=> (a -> m) -> t a -> m
foldMapDefault f xs =
getConst (traverse (Const . f) xs)
As this applies to Maybe,
foldMapDefault f Nothing =
getConst (traverse (Const . f) Nothing)
foldMapDefault f (Just a) =
getConst (traverse (Const . f) (Just a))
Expanding our definitions,
foldMapDefault f Nothing = getConst (pure Nothing)
foldMapDefault f (Just a) = getConst (Just <$> (Const (f a)))
By the definitions of pure and <$> for Const, these are
foldMapDefault f Nothing = getConst (Const mempty)
foldMapDefault f (Just a) = getConst (Const (f a))
Unwrapping the constructor,
foldMapDefault f Nothing = mempty
foldMapDefault f (Just a) = f a
And this is indeed exactly how foldMap is defined for Maybe.
As "basic concepts" go, this is pretty mind-bending, so don't feel too bad.
It may help to set aside your intuition about what a fold does to a list and think about what type a specific folding function (let's use foldr) should have if applied to a Maybe. Writing List a in place of [a] to make it clearer, the standard foldr on a list has type:
foldr :: (a -> b -> b) -> b -> List a -> b
Obviously, the corresponding fold on a Maybe must have type:
foldrMaybe :: (a -> b -> b) -> b -> Maybe a -> b
Think about what definition this could possibly have, given that it must be defined for all a and b without knowing anything else about the types. As a further hint, see if there's a function already defined in Data.Maybe that has a similar type -- maybe (ha ha) that'll give you some ideas.
I just read the following from typeclassopedia about the difference between Monad and Applicative. I can understand that there is no join in Applicative. But the following description looks vague to me and I couldn't figure out what exactly is meant by "the result" of a monadic computation/action. So, if I put a value into Maybe, which makes a monad, what is the result of this "computation"?
Let’s look more closely at the type of (>>=). The basic intuition is
that it combines two computations into one larger computation. The
first argument, m a, is the first computation. However, it would be
boring if the second argument were just an m b; then there would be no
way for the computations to interact with one another (actually, this
is exactly the situation with Applicative). So, the second argument to
(>>=) has type a -> m b: a function of this type, given a result of
the first computation, can produce a second computation to be run.
... Intuitively, it is this ability to use the output from previous
computations to decide what computations to run next that makes Monad
more powerful than Applicative. The structure of an Applicative
computation is fixed, whereas the structure of a Monad computation can
change based on intermediate results.
Is there a concrete example illustrating "ability to use the output from previous computations to decide what computations to run next", which Applicative does not have?
My favorite example is the "purely applicative Either". We'll start by analyzing the base Monad instance for Either
instance Monad (Either e) where
return = Right
Left e >>= _ = Left e
Right a >>= f = f a
This instance embeds a very natural short-circuiting notion: we proceed from left to right and once a single computation "fails" into the Left then all the rest do as well. There's also the natural Applicative instance that any Monad has
instance Applicative (Either e) where
pure = return
(<*>) = ap
where ap is nothing more than left-to-right sequencing before a return:
ap :: Monad m => m (a -> b) -> m a -> m b
ap mf ma = do
f <- mf
a <- ma
return (f a)
Now the trouble with this Either instance comes to light when you'd like to collect error messages which occur anywhere in a computation and somehow produce a summary of errors. This flies in the face of short-circuiting. It also flies in the face of the type of (>>=)
(>>=) :: m a -> (a -> m b) -> m b
If we think of m a as "the past" and m b as "the future" then (>>=) produces the future from the past so long as it can run the "stepper" (a -> m b). This "stepper" demands that the value of a really exists in the future... and this is impossible for Either. Therefore (>>=) demands short-circuiting.
So instead we'll implement an Applicative instance which cannot have a corresponding Monad.
instance Monoid e => Applicative (Either e) where
pure = Right
Now the implementation of (<*>) is the special part worth considering carefully. It performs some amount of "short-circuiting" in its first 3 cases, but does something interesting in the fourth.
Right f <*> Right a = Right (f a) -- neutral
Left e <*> Right _ = Left e -- short-circuit
Right _ <*> Left e = Left e -- short-circuit
Left e1 <*> Left e2 = Left (e1 <> e2) -- combine!
Notice again that if we think of the left argument as "the past" and the right argument as "the future" then (<*>) is special compared to (>>=) as it's allowed to "open up" the future and the past in parallel instead of necessarily needing results from "the past" in order to compute "the future".
This means, directly, that we can use our purely Applicative Either to collect errors, ignoring Rights if any Lefts exist in the chain
> Right (+1) <*> Left [1] <*> Left [2]
> Left [1,2]
So let's flip this intuition on its head. What can we not do with a purely applicative Either? Well, since its operation depends upon examining the future prior to running the past, we must be able to determine the structure of the future without depending upon values in the past. In other words, we cannot write
ifA :: Applicative f => f Bool -> f a -> f a -> f a
which satisfies the following equations
ifA (pure True) t e == t
ifA (pure False) t e == e
while we can write ifM
ifM :: Monad m => m Bool -> m a -> m a -> m a
ifM mbool th el = do
bool <- mbool
if bool then th else el
such that
ifM (return True) t e == t
ifM (return False) t e == e
This impossibility arises because ifA embodies exactly the idea of the result computation depending upon the values embedded in the argument computations.
Just 1 describes a "computation", whose "result" is 1. Nothing describes a computation which produces no results.
The difference between a Monad and an Applicative is that in the Monad there's a choice. The key distinction of Monads is the ability to choose between different paths in computation (not just break out early). Depending on a value produced by a previous step in computation, the rest of computation structure can change.
Here's what this means. In the monadic chain
return 42 >>= (\x ->
if x == 1
then
return (x+1)
else
return (x-1) >>= (\y ->
return (1/y) ))
the if chooses what computation to construct.
In case of Applicative, in
pure (1/) <*> ( pure (+(-1)) <*> pure 1 )
all the functions work "inside" computations, there's no chance to break up a chain. Each function just transforms a value it's fed. The "shape" of the computation structure is entirely "on the outside" from the functions' point of view.
A function could return a special value to indicate failure, but it can't cause next steps in the computation to be skipped. They all will have to process the special value in a special way too. The shape of the computation can not be changed according to received value.
With monads, the functions themselves construct computations to their choosing.
Here is my take on #J. Abrahamson's example as to why ifA cannot use the value inside e.g. (pure True). In essence, it still boils down to the absence of the join function from Monad in Applicative, which unifies the two different perspectives given in typeclassopedia to explain the difference between Monad and Applicative.
So using #J. Abrahamson's example of purely applicative Either:
instance Monoid e => Applicative (Either e) where
pure = Right
Right f <*> Right a = Right (f a) -- neutral
Left e <*> Right _ = Left e -- short-circuit
Right _ <*> Left e = Left e -- short-circuit
Left e1 <*> Left e2 = Left (e1 <> e2) -- combine!
(which has similar short-circuiting effect to the Either Monad), and the ifA function
ifA :: Applicative f => f Bool -> f a -> f a -> f a
What if we try to achieve the mentioned equations:
ifA (pure True) t e == t
ifA (pure False) t e == e
?
Well, as already pointed out, ultimately, the content of (pure True), cannot be used by a later computation. But technically speaking, this isn't right. We can use the content of (pure True) since a Monad is also a Functor with fmap. We can do:
ifA' b t e = fmap (\x -> if x then t else e) b
The problem is with the return type of ifA', which is f (f a). In Applicative, there is no way of collapsing two nested ApplicativeS into one. But this collapsing function is precisely what join in Monad performs. So,
ifA = join . ifA'
will satisfy the equations for ifA, if we can implement join appropriately. What Applicative is missing here is exactly the join function. In other words, we can somehow use the result from the previous result in Applicative. But doing so in an Applicative framework will involve augmenting the type of the return value to a nested applicative value, which we have no means to bring back to a single-level applicative value. This will be a serious problem because, e.g., we cannot compose functions using ApplicativeS appropriately. Using join fixes the issue, but the very introduction of join promotes the Applicative to a Monad.
The key of the difference can be observed in the type of ap vs type of =<<.
ap :: m (a -> b) -> (m a -> m b)
=<< :: (a -> m b) -> (m a -> m b)
In both cases there is m a, but only in the second case m a can decide whether the function (a -> m b) gets applied. In its turn, the function (a -> m b) can "decide" whether the function bound next gets applied - by producing such m b that does not "contain" b (like [], Nothing or Left).
In Applicative there is no way for functions "inside" m (a -> b) to make such "decisions" - they always produce a value of type b.
f 1 = Nothing -- here f "decides" to produce Nothing
f x = Just x
Just 1 >>= f >>= g -- g doesn't get applied, because f decided so.
In Applicative this is not possible, so can't show a example. The closest is:
f 1 = 0
f x = x
g <$> f <$> Just 1 -- oh well, this will produce Just 0, but can't stop g
-- from getting applied
But the following description looks vague to me and I couldn't figure out what exactly is meant by "the result" of a monadic computation/action.
Well, that vagueness is somewhat deliberate, because what "the result" is of a monadic computation is something that depends on each type. The best answer is a bit tautological: the "result" (or results, since there can be more than one) is whatever value(s) the instance's implementation of (>>=) :: Monad m => m a -> (a -> m b) -> m b invokes the function argument with.
So, if I put a value into Maybe, which makes a monad, what is the result of this "computation"?
The Maybe monad looks like this:
instance Monad Maybe where
return = Just
Nothing >>= _ = Nothing
Just a >>= k = k a
The only thing in here that qualifies as a "result" is the a in the second equation for >>=, because it's the only thing that ever gets "fed" to the second argument of >>=.
Other answers have gone into depth about the ifA vs. ifM difference, so I thought I'd highlight another significant difference: applicatives compose, monads don't. With Monads, if you want to make a Monad that combines the effects of two existing ones, you have to rewrite one of them as a monad transformer. In contrast, if you have two Applicatives you can easily make a more complex one out of them, as shown below. (Code is copypasted from transformers.)
-- | The composition of two functors.
newtype Compose f g a = Compose { getCompose :: f (g a) }
-- | The composition of two functors is also a functor.
instance (Functor f, Functor g) => Functor (Compose f g) where
fmap f (Compose x) = Compose (fmap (fmap f) x)
-- | The composition of two applicatives is also an applicative.
instance (Applicative f, Applicative g) => Applicative (Compose f g) where
pure x = Compose (pure (pure x))
Compose f <*> Compose x = Compose ((<*>) <$> f <*> x)
-- | The product of two functors.
data Product f g a = Pair (f a) (g a)
-- | The product of two functors is also a functor.
instance (Functor f, Functor g) => Functor (Product f g) where
fmap f (Pair x y) = Pair (fmap f x) (fmap f y)
-- | The product of two applicatives is also an applicative.
instance (Applicative f, Applicative g) => Applicative (Product f g) where
pure x = Pair (pure x) (pure x)
Pair f g <*> Pair x y = Pair (f <*> x) (g <*> y)
-- | The sum of a functor #f# with the 'Identity' functor
data Lift f a = Pure a | Other (f a)
-- | The sum of two functors is always a functor.
instance (Functor f) => Functor (Lift f) where
fmap f (Pure x) = Pure (f x)
fmap f (Other y) = Other (fmap f y)
-- | The sum of any applicative with 'Identity' is also an applicative
instance (Applicative f) => Applicative (Lift f) where
pure = Pure
Pure f <*> Pure x = Pure (f x)
Pure f <*> Other y = Other (f <$> y)
Other f <*> Pure x = Other (($ x) <$> f)
Other f <*> Other y = Other (f <*> y)
Now, if we add in the Constant functor/applicative:
newtype Constant a b = Constant { getConstant :: a }
instance Functor (Constant a) where
fmap f (Constant x) = Constant x
instance (Monoid a) => Applicative (Constant a) where
pure _ = Constant mempty
Constant x <*> Constant y = Constant (x `mappend` y)
...we can assemble the "applicative Either" from the other responses out of Lift and Constant:
type Error e a = Lift (Constant e) a
As #Will Ness explains in his answer, the key difference is that with Monads there's a choice between different executions paths at every step. Let's make this potential choice syntactically visible by implementing a function for sequencing four times. First for applicative f, and then for monad m:
seq4A :: Applicative f => f a -> f [a]
seq4A f =
f <**> (
f <**> (
f <**> (
f <&> (\a1 a2 a3 a4 ->
[a1, a2, a3, a4]))))
seq4M :: Monad m => m a -> m [a]
seq4M m =
m >>= (\a1 ->
m >>= (\a2 ->
m >>= (\a3 ->
m >>= (\a4 ->
return [a1, a2, a3, a4]))))
The seq4M function has the values resulting from the monadic action available at every step and could thus make a choice at every step. On the other hand the seq4A function only has the values available at the very end.
I would like to share my view on this "iffy miffy" thing, as I understand this everything inside the context get applied, so for example:
iffy :: Applicative f => f Bool -> f a -> f a -> f a
iffy fb ft fe = cond <$> fb <*> ft <*> fe where
cond b t e = if b then t else e
case 1>> iffy (Just True) (Just “True”) Nothing ->> Nothing
upps should be Just "True" ... but
case 2>> iffy (Just False) (Just “True”) (Just "False") ->> Just "False"
(the "good" choice is made inside the context)
I explained this to myself this way, just before the end of the computation in case >>1 we get something like that in the "chain" :
Just (Cond True "True") <*> something [something being "accidentaly" Nothing]
which according by definition of Applicative is evaluated as:
fmap (Cond True "True") something
which when "something" is Nothing becomes a Nothing according to Functor constraint (fmap over Nothing gives Nothing). And it is not possible to define a Functor with "fmap f Nothing = something" end of story.
I´am trying to desugar a do statement in Haskell. I have found some examples here on SO but wasn´t able to apply them to my case.
Only thing I can think of is a heavy nested let statement, which seems quite ugly.
Statement in which do notation should be replaced by bind:
do num <- numberNode x
nt1 <- numberTree t1
nt2 <- numberTree t2
return (Node num nt1 nt2)
Any input is highly appreciated =)
numberNode x >>= \num ->
numberTree t1 >>= \nt1 ->
numberTree t2 >>= \nt2 ->
return (Node num nt1 nt2)
Note that this is simpler if you use Applicatives:
Node <$> numberNode x <*> numberTree t1 <*> numberTree t2
This is an excellent use case for applicative style. You can replace your entire snippet (after importing Control.Applicative) with
Node <$> numberNode x <*> numberTree t1 <*> numberTree t2
Think of the applicative style (using <$> and <*>) as "lifting" function application so it works on functors as well. If you mentally ignore <$> and <*> it looks quite a lot like normal function application!
Applicative style is useful whenever you have a pure function and you want to give it impure arguments (or any functor arguments, really) -- basically when you want to do what you specified in your question!
The type signature of <$> is
(<$>) :: Functor f => (a -> b) -> f a -> f b
which means it takes a pure function (in this case Node) and a functor value (in this case numberNode x) and it creates a new function wrapped "inside" a functor. You can add further arguments to this function with <*>, which has the type signature
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
As you can see, this is very similar to <$> only it works even when the function is wrapped "inside" a functor.
I'd like to add to the posts about Applicative above..
Considering the type of <$>:
(<$>) :: Functor f => (a -> b) -> f a -> f b
it looks just like fmap:
fmap :: Functor f => (a -> b) -> f a -> f b
which is also very much like Control.Monad.liftM:
liftM :: Monad m => (a -> b) -> m a -> m b
I think of this as "I need to lift the data constructor into this type"
On a related note, if you find yourself doing this:
action >>= return . f
you can instead do this:
f `fmap` action
The first example is using bind to take the value out of whatever type action is, calling f with it, and then repacking the result. Instead, we can lift f so that it takes the type of action as its argument.
I've been trying to "learn me a Haskell" through the online book LYAH.
The author describes the behaviour of Functors of the Applicative type as sort of having the ability to extract a function from one functor and mapping it over a second functor; this is through the <*> function declared for the Applicative type class:
class (Functor f) => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
As a simple example, the Maybe type is an instance of Applicative under the following implementation:
instance Applicative Maybe where
pure = Just
Nothing <*> _ = Nothing
(Just f) <*> something = fmap f something
An example of the behaviour mentioned previously:
ghci> Just (*2) <*> Just 10 -- evaluates to Just 20
so the <*> operator "extracts" the (*2) function from the first operand and maps it over the second operand.
Now in Applicative types, both operands of <*> are of the same type, so I thought as an exercise why not try implementing a generalisation of this behaviour, where the two operands are Functors of different types, so I could evaluate something like this:
Just (2*) <*:*> [1,2,3,4] -- should evaluate to [2,4,6,8]
So this is what I came up with:
import Control.Applicative
class (Applicative f, Functor g) => DApplicative f g where
pure1 :: a -> f a
pure1 = pure
(<*:*>) :: f ( a -> b ) -> g a -> g b -- referred below as (1)
instance DApplicative Maybe [] where -- an "instance pair" of this class
(Just func) <*:*> g = fmap func g
main = do putStrLn(show x)
where x = Just (2*) <*:*> [1,2,3,4] -- it works, x equals [2,4,6,8]
Now, although the above works, I'm wondering if we can do better; is it possible to give a default implementation for <*:*> that can be applied to a variety of f & g pairs, in the declaration for DApplicative f g itself? And this leads me to the following question: Is there a way to pattern match on constructors across different data types?
I hope my questions make some sense and I'm not just spewing nonsense (if I am, please don't be too harsh; I'm just an FP beginner up way past his bedtime...)
This does make sense, but it ends up being not particularly useful in its current form. The problem is exactly what you've noticed: there is no way to provide a default which does sensible things with different types, or to generally convert from f to g. So you'd have a quadratic explosion in the number of instances you'd need to write.
You didn't finish the DApplicative instance. Here's a full implementation for Maybe and []:
instance DApplicative Maybe [] where -- an "instance pair" of this class
(Just func) <*:*> g = fmap func g
Nothing <*:*> g = []
This combines the behaviors of both Maybe and [], because with Just it does what you expect, but with Nothing it returns nothing, an empty list.
So instead of writing DApplicative which takes two different types, what if you had a way of combining two applicatives f and g into a single type? If you generalize this action, you could then use a standard Applicative with the new type.
This could be done with the standard formulation of Applicatives as
liftAp :: f (g (a -> b)) -> f (g a) -> f (g b)
liftAp l r = (<*>) <$> l <*> r
but instead let's change Maybe:
import Control.Applicative
newtype MaybeT f a = MaybeT { runMaybeT :: f (Maybe a) }
instance (Functor f) => Functor (MaybeT f) where
fmap f (MaybeT m) = MaybeT ((fmap . fmap) f m)
instance (Applicative f) => Applicative (MaybeT f) where
pure a = MaybeT (pure (pure a))
(MaybeT f) <*> (MaybeT m) = MaybeT ( (<*>) <$> f <*> m)
Now you just need a way to convert something in the inner applicative, f, into the combined applicative MaybeT f:
lift :: (Functor f) => f a -> MaybeT f a
lift = MaybeT . fmap Just
This looks like a lot of boilerplate, but ghc can automatically derive nearly all of it.
Now you can easily use the combined functions:
*Main Control.Applicative> runMaybeT $ pure (*2) <*> lift [1,2,3,4]
[Just 2,Just 4,Just 6,Just 8]
*Main Control.Applicative> runMaybeT $ MaybeT (pure Nothing) <*> lift [1,2,3,4]
[Nothing,Nothing,Nothing,Nothing]
This behavior at Nothing may be surprising, but if you think of a list as representing indeterminism you can probably see how it could be useful. If you wanted the dual behavior of returning either Just [a] or Nothing, you just need a transformed List ListT Maybe a.
This isn't quite the same as the instance I wrote for DApplicative. The reason is because of the types. DApplicative converts an f into a g. That's only possible when you know the specific f and g. To generalize it, the result needs to combine the behaviors of both f and g as this implementation does.
All of this works with Monads too. Transformed types such as MaybeT are provided by monad transformer libraries such as mtl.
Your DApplicative instance for Maybe is not complete: What should happen if the first argument of <*:*> is Nothing?
The choice what to do for every combination isn't clear. For two lists <*> would generate all combinations: [(+2),(+10)] <*> [3,4] gives [5,6,13,14]. For two ZipLists you have a zip-like behaviour: (ZipList [(+2),(+10)]) <*> (ZipList [3,4]) gives [5,14]. So you have to choose one of both possible behaviours for a DApplicative of a list and a ZipList, there is no "correct" version.
In my free time I'm learning Haskell, so this is a beginner question.
In my readings I came across an example illustrating how Either a is made an instance of Functor:
instance Functor (Either a) where
fmap f (Right x) = Right (f x)
fmap f (Left x) = Left x
Now, I'm trying to understand why the implementation maps in the case of a Right value constructor, but doesn't in the case of a Left?
Here is my understanding:
First let me rewrite the above instance as
instance Functor (Either a) where
fmap g (Right x) = Right (g x)
fmap g (Left x) = Left x
Now:
I know that fmap :: (c -> d) -> f c -> f d
if we substitute f with Either a we get fmap :: (c -> d) -> Either a c -> Either a d
the type of Right (g x) is Either a (g x), and the type of g x is d, so we have that the type of Right (g x) is Either a d, which is what we expect from fmap (see 2. above)
now, if we look at Left (g x) we can use the same reasoning to say that its type is Either (g x) b, that is Either d b, which is not what we expect from fmap (see 2. above): the d should be the second parameter, not the first! So we can't map over Left.
Is my reasoning correct?
This is right. There is also another quite important reason for this behavior: You can think of Either a b as a computation, that may succeed and return b or fail with an error message a. (This is also, how the monad instance works). So it's only natural, that the functor instance won't touch the Left values, since you want to map over the computation, if it fails, there's nothing to manipulate.
Your account is right of course. Maybe the reason why we have a difficulty with instances like this is that we are really defining infinitely many functor instances at once -- one for each possible Left type. But a Functor instance is a systematic way of operating on the infinitely many types in the system. So we are defining infinitely many ways of systematically operating on the infinitely many types in the system. The instance involves generality in two ways.
If you take it by stages, though, maybe it's not so strange. The first of these types is a longwinded version of Maybe using the unit type () and its only legitimate value ():
data MightBe b = Nope () | Yep b
data UnlessError b = Bad String | Good b
data ElseInt b = Else Int | Value b
Here we might get tired and make an abstraction:
data Unless a b = Mere a | Genuine b
Now we make our Functor instances, unproblematically, the first looking a lot like the instance for Maybe:
instance Functor MightBe where
fmap f (Nope ()) = Nope () -- compare with Nothing
fmap f (Yep x) = Yep (f x) -- compare with Just (f x)
instance Functor UnlessError where
fmap f (Bad str) = Bad str -- a more informative Nothing
fmap f (Good x) = Good (f x)
instance Functor ElseInt where
fmap f (Else n) = Else n
fmap f (Value b) = Value (f b)
But, again, why bother, let's make the abstraction:
instance Functor (Unless a) where
fmap f (Mere a) = Mere a
fmap f (Genuine x) = Genuine (f x)
The Mere a terms aren't touched, as the (), String and Int values weren't touched.
As others mentioned, Either type is a functor in its both arguments. But in Haskell we are able to (directly) define only functors in a type's last arguments. In cases like this, we can get around the limitation by using newtypes:
newtype FlipEither b a = FlipEither { unFlipEither :: Either a b }
So we have constructor FlipEither :: Either a b -> FlipEither b a that wraps an Either into our newtype with swapped type arguments. And we have dectructor unFlipEither :: FlipEither b a -> Either a b that unwraps it back. Now we can define a functor instance in FlipEither's last argument, which is actually Either's first argument:
instance Functor (FlipEither b) where
fmap f (FlipEither (Left x)) = FlipEither (Left (f x))
fmap f (FlipEither (Right x)) = FlipEither (Right x)
Notice that if we forget FlipEither for a while we get just the definition of Functor for Either, just with Left/Right swapped. And now, whenever we need a Functor instance in Either's first type argument, we can wrap the value into FlipEither and unwrap it afterward. For example:
fmapE2 :: (a -> b) -> Either a c -> Either b c
fmapE2 f = unFlipEither . fmap f . FlipEither
Update: Have a look at Data.Bifunctor, of which Either and (,) are instances of. Each bifunctor has two arguments and is a functor in each of them. This is reflected in Bifunctor's methods first and second.
The definition of Bifunctor of Either is very symetric:
instance Bifunctor Either where
bimap f _ (Left a) = Left (f a)
bimap _ g (Right b) = Right (g b)
first f = bimap f id
second f = bimap id f
Now, I'm trying to understand why the
implementation maps in the case of a
Right value constructor, but doesn't
in the case of a Left?
Plug in here and it might make sense.
Assume a = String (an error message)
You apply Either a to an Float.
So you have an f: Float -> Integer say for example roundoff.
(Either String) (Float) = Either String Float.
now (fmap f):: Either String Float -> Either String Int
So what are you going to do with f? f doesn't have a clue what to do with strings so you can't do anything there. That is obviously the only thing you can act on are the right values while leaving the left values unchanged.
In other words Either a is a functor because there is such an obvious fmap given by:
for Right values apply f
for Left values do nothing