Do the monadic liftM and the functorial fmap have to be equivalent?
up vote
6
down vote
favorite
(Note: I'm phrasing the question using Haskell terminology; answers are welcome to use the same terminology and/or the mathematical language of category theory, including proper mathematical definitions and axioms where I speak of functor and monad laws.)
It is well known that every monad is also a functor, with the functor's fmap equivalent to the monad's liftM. This makes sense, and of course holds for all common/reasonable monad instances.
My question is whether this equivalence of fmap and liftM provably follows from the functor and monad laws. If so it will be nice to see how, and if not it will be nice to see a counterexample.
To clarify, the functor and monad laws I know are the following:
fmap id≡idfmap f . fmap g≡fmap (f . g)return x >>= f≡f xx >>= return≡x(x >>= f) >>= g≡x >>= (x -> f x >>= g)
I don't see anything in these laws which relates the functor functionality (fmap) to the monad functionality (return and >>=), and so I find it hard to see how the equivalence of fmap and liftM (defined as liftM f x = x >>= (return . f)) can be derived from them. Maybe there is an argument for it which is just not straightforward enough for me to spot? Or maybe I'm missing some laws?
haskell category-theory
add a comment |
up vote
6
down vote
favorite
(Note: I'm phrasing the question using Haskell terminology; answers are welcome to use the same terminology and/or the mathematical language of category theory, including proper mathematical definitions and axioms where I speak of functor and monad laws.)
It is well known that every monad is also a functor, with the functor's fmap equivalent to the monad's liftM. This makes sense, and of course holds for all common/reasonable monad instances.
My question is whether this equivalence of fmap and liftM provably follows from the functor and monad laws. If so it will be nice to see how, and if not it will be nice to see a counterexample.
To clarify, the functor and monad laws I know are the following:
fmap id≡idfmap f . fmap g≡fmap (f . g)return x >>= f≡f xx >>= return≡x(x >>= f) >>= g≡x >>= (x -> f x >>= g)
I don't see anything in these laws which relates the functor functionality (fmap) to the monad functionality (return and >>=), and so I find it hard to see how the equivalence of fmap and liftM (defined as liftM f x = x >>= (return . f)) can be derived from them. Maybe there is an argument for it which is just not straightforward enough for me to spot? Or maybe I'm missing some laws?
haskell category-theory
add a comment |
up vote
6
down vote
favorite
up vote
6
down vote
favorite
(Note: I'm phrasing the question using Haskell terminology; answers are welcome to use the same terminology and/or the mathematical language of category theory, including proper mathematical definitions and axioms where I speak of functor and monad laws.)
It is well known that every monad is also a functor, with the functor's fmap equivalent to the monad's liftM. This makes sense, and of course holds for all common/reasonable monad instances.
My question is whether this equivalence of fmap and liftM provably follows from the functor and monad laws. If so it will be nice to see how, and if not it will be nice to see a counterexample.
To clarify, the functor and monad laws I know are the following:
fmap id≡idfmap f . fmap g≡fmap (f . g)return x >>= f≡f xx >>= return≡x(x >>= f) >>= g≡x >>= (x -> f x >>= g)
I don't see anything in these laws which relates the functor functionality (fmap) to the monad functionality (return and >>=), and so I find it hard to see how the equivalence of fmap and liftM (defined as liftM f x = x >>= (return . f)) can be derived from them. Maybe there is an argument for it which is just not straightforward enough for me to spot? Or maybe I'm missing some laws?
haskell category-theory
(Note: I'm phrasing the question using Haskell terminology; answers are welcome to use the same terminology and/or the mathematical language of category theory, including proper mathematical definitions and axioms where I speak of functor and monad laws.)
It is well known that every monad is also a functor, with the functor's fmap equivalent to the monad's liftM. This makes sense, and of course holds for all common/reasonable monad instances.
My question is whether this equivalence of fmap and liftM provably follows from the functor and monad laws. If so it will be nice to see how, and if not it will be nice to see a counterexample.
To clarify, the functor and monad laws I know are the following:
fmap id≡idfmap f . fmap g≡fmap (f . g)return x >>= f≡f xx >>= return≡x(x >>= f) >>= g≡x >>= (x -> f x >>= g)
I don't see anything in these laws which relates the functor functionality (fmap) to the monad functionality (return and >>=), and so I find it hard to see how the equivalence of fmap and liftM (defined as liftM f x = x >>= (return . f)) can be derived from them. Maybe there is an argument for it which is just not straightforward enough for me to spot? Or maybe I'm missing some laws?
haskell category-theory
haskell category-theory
asked Oct 27 at 12:54
Tom
2,45312039
2,45312039
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
up vote
9
down vote
What you have missed is the parametericity law, otherwise known as the free theorem. One of the consequences of parametricity is that all polymorphic functions are natural transformations. Naturality says that any polymorphic function of the form
t :: F a -> G a
where F and G are functors, commutes with fmap:
t . fmap f = fmap f . t
If we can make something involving liftM that has the form of a natural transformation, then we will have an equation relating liftM and fmap. liftM itself doesn't produce a natural transformation:
liftM :: (a -> b) -> m a -> m b
-- ^______^
-- these need to be the same
But here's an idea, since (a ->) is a functor:
as :: m a
flip liftM as :: (a -> b) -> m b
-- F b -> G b
Let's try using parametericity on flip liftM m:
flip liftM m . fmap f = fmap f . flip liftM m
The former fmap is on the (a ->) functor, where fmap = (.), so
flip liftM m . (.) f = fmap f . flip liftM m
Eta expand
(flip liftM m . (.) f) g = (fmap f . flip liftM m) g
flip liftM m (f . g) = fmap f (flip liftM m g)
liftM (f . g) m = fmap f (liftM g m)
This is promising. Take g = id:
liftM (f . id) m = fmap f (liftM id m)
liftM f m = fmap f (liftM id m)
It would suffice to show liftM id = id. That probably follows from its definition:
liftM id m
= m >>= return . id
= m >>= return
= m
Yep! Qed.
6
Yup. Parametricity means that functions with thefmaptype that takeidtoidare unique, and from the definition ofliftMit follows thatliftM id = id, thereforeliftM = fmap. Cf. my answer to a very similar question.
– duplode
Oct 27 at 15:22
2
So, just to clarify: You can define a monad as a type constructorm, with two polymorphic functions>>=andreturn; and it is automatically a functor, with the action on morphisms defined byliftM. The question is: What if I define another functor, whose action on objects (the type constructorm) is the same, but whose action on morphisms (fmap) is different? You are free to do that in category theory, but if you try to do it in Haskell, you're limited by parametricity, which tells you thatfmapfor a given type constructor is unique, as long as it maps identity to identity.
– Bartosz Milewski
2 days ago
add a comment |
up vote
6
down vote
For this exercise, I found it easier to work with join rather than >>=. A monad can be equivalently defined through return and join, satisfying
1) join . join = join . fmap join
2) join . return = join . fmap return = id
Indeed, join and >>= are inter-definable:
x >>= f = join (fmap f x)
join x = x >>= id
And the laws you mentioned correspond to those above (I won't prove this).
Then, we have:
liftM f x
= def liftM
x >>= return . f
= def >>=
join (fmap (return . f) x)
= def . and $
join . fmap (return . f) $ x
= fmap law
join . fmap return . fmap f $ x
= join law 2
id . fmap f $ x
= def id, ., $
fmap f x
I am not sure I am satisfied with this, sincefmapappears in the join laws. Imagine back in the days whenFunctorwas not a superclass ofMonad. That is, I suspect "the laws .. correspond to those above" elides some technical dragons which undermine this argument.
– luqui
Oct 27 at 13:20
@luqui I used that to sweep parametricity under the rug :-P. The OP explicitly mentions "It is well known that every monad is also a functor", so I only focused on "real" monads, in the mathematical sense. I actually prefer your approach to mine since it clearly shows parametricity in action, and avoids passing through an equivalent axiomatization.
– chi
Oct 27 at 13:25
2
You are answering a slightly different question. The definition of a monad usingjoinandreturnalso requiresfmap. On the other hand, using those three you can defineliftM. You're showing that thisliftMis the same as the originalfmap. This doesn't require parametricity. It is true in any category.
– Bartosz Milewski
2 days ago
this answer answers the question exactly as asked, "how the equivalence offmapandliftM(defined asliftM f x = x >>= (return . f)) can be derived from [the laws]". the other question answers a wider question, "is the functionliftMwithfmap's type necessarily equivalent tofmap".
– Will Ness
2 days ago
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
9
down vote
What you have missed is the parametericity law, otherwise known as the free theorem. One of the consequences of parametricity is that all polymorphic functions are natural transformations. Naturality says that any polymorphic function of the form
t :: F a -> G a
where F and G are functors, commutes with fmap:
t . fmap f = fmap f . t
If we can make something involving liftM that has the form of a natural transformation, then we will have an equation relating liftM and fmap. liftM itself doesn't produce a natural transformation:
liftM :: (a -> b) -> m a -> m b
-- ^______^
-- these need to be the same
But here's an idea, since (a ->) is a functor:
as :: m a
flip liftM as :: (a -> b) -> m b
-- F b -> G b
Let's try using parametericity on flip liftM m:
flip liftM m . fmap f = fmap f . flip liftM m
The former fmap is on the (a ->) functor, where fmap = (.), so
flip liftM m . (.) f = fmap f . flip liftM m
Eta expand
(flip liftM m . (.) f) g = (fmap f . flip liftM m) g
flip liftM m (f . g) = fmap f (flip liftM m g)
liftM (f . g) m = fmap f (liftM g m)
This is promising. Take g = id:
liftM (f . id) m = fmap f (liftM id m)
liftM f m = fmap f (liftM id m)
It would suffice to show liftM id = id. That probably follows from its definition:
liftM id m
= m >>= return . id
= m >>= return
= m
Yep! Qed.
6
Yup. Parametricity means that functions with thefmaptype that takeidtoidare unique, and from the definition ofliftMit follows thatliftM id = id, thereforeliftM = fmap. Cf. my answer to a very similar question.
– duplode
Oct 27 at 15:22
2
So, just to clarify: You can define a monad as a type constructorm, with two polymorphic functions>>=andreturn; and it is automatically a functor, with the action on morphisms defined byliftM. The question is: What if I define another functor, whose action on objects (the type constructorm) is the same, but whose action on morphisms (fmap) is different? You are free to do that in category theory, but if you try to do it in Haskell, you're limited by parametricity, which tells you thatfmapfor a given type constructor is unique, as long as it maps identity to identity.
– Bartosz Milewski
2 days ago
add a comment |
up vote
9
down vote
What you have missed is the parametericity law, otherwise known as the free theorem. One of the consequences of parametricity is that all polymorphic functions are natural transformations. Naturality says that any polymorphic function of the form
t :: F a -> G a
where F and G are functors, commutes with fmap:
t . fmap f = fmap f . t
If we can make something involving liftM that has the form of a natural transformation, then we will have an equation relating liftM and fmap. liftM itself doesn't produce a natural transformation:
liftM :: (a -> b) -> m a -> m b
-- ^______^
-- these need to be the same
But here's an idea, since (a ->) is a functor:
as :: m a
flip liftM as :: (a -> b) -> m b
-- F b -> G b
Let's try using parametericity on flip liftM m:
flip liftM m . fmap f = fmap f . flip liftM m
The former fmap is on the (a ->) functor, where fmap = (.), so
flip liftM m . (.) f = fmap f . flip liftM m
Eta expand
(flip liftM m . (.) f) g = (fmap f . flip liftM m) g
flip liftM m (f . g) = fmap f (flip liftM m g)
liftM (f . g) m = fmap f (liftM g m)
This is promising. Take g = id:
liftM (f . id) m = fmap f (liftM id m)
liftM f m = fmap f (liftM id m)
It would suffice to show liftM id = id. That probably follows from its definition:
liftM id m
= m >>= return . id
= m >>= return
= m
Yep! Qed.
6
Yup. Parametricity means that functions with thefmaptype that takeidtoidare unique, and from the definition ofliftMit follows thatliftM id = id, thereforeliftM = fmap. Cf. my answer to a very similar question.
– duplode
Oct 27 at 15:22
2
So, just to clarify: You can define a monad as a type constructorm, with two polymorphic functions>>=andreturn; and it is automatically a functor, with the action on morphisms defined byliftM. The question is: What if I define another functor, whose action on objects (the type constructorm) is the same, but whose action on morphisms (fmap) is different? You are free to do that in category theory, but if you try to do it in Haskell, you're limited by parametricity, which tells you thatfmapfor a given type constructor is unique, as long as it maps identity to identity.
– Bartosz Milewski
2 days ago
add a comment |
up vote
9
down vote
up vote
9
down vote
What you have missed is the parametericity law, otherwise known as the free theorem. One of the consequences of parametricity is that all polymorphic functions are natural transformations. Naturality says that any polymorphic function of the form
t :: F a -> G a
where F and G are functors, commutes with fmap:
t . fmap f = fmap f . t
If we can make something involving liftM that has the form of a natural transformation, then we will have an equation relating liftM and fmap. liftM itself doesn't produce a natural transformation:
liftM :: (a -> b) -> m a -> m b
-- ^______^
-- these need to be the same
But here's an idea, since (a ->) is a functor:
as :: m a
flip liftM as :: (a -> b) -> m b
-- F b -> G b
Let's try using parametericity on flip liftM m:
flip liftM m . fmap f = fmap f . flip liftM m
The former fmap is on the (a ->) functor, where fmap = (.), so
flip liftM m . (.) f = fmap f . flip liftM m
Eta expand
(flip liftM m . (.) f) g = (fmap f . flip liftM m) g
flip liftM m (f . g) = fmap f (flip liftM m g)
liftM (f . g) m = fmap f (liftM g m)
This is promising. Take g = id:
liftM (f . id) m = fmap f (liftM id m)
liftM f m = fmap f (liftM id m)
It would suffice to show liftM id = id. That probably follows from its definition:
liftM id m
= m >>= return . id
= m >>= return
= m
Yep! Qed.
What you have missed is the parametericity law, otherwise known as the free theorem. One of the consequences of parametricity is that all polymorphic functions are natural transformations. Naturality says that any polymorphic function of the form
t :: F a -> G a
where F and G are functors, commutes with fmap:
t . fmap f = fmap f . t
If we can make something involving liftM that has the form of a natural transformation, then we will have an equation relating liftM and fmap. liftM itself doesn't produce a natural transformation:
liftM :: (a -> b) -> m a -> m b
-- ^______^
-- these need to be the same
But here's an idea, since (a ->) is a functor:
as :: m a
flip liftM as :: (a -> b) -> m b
-- F b -> G b
Let's try using parametericity on flip liftM m:
flip liftM m . fmap f = fmap f . flip liftM m
The former fmap is on the (a ->) functor, where fmap = (.), so
flip liftM m . (.) f = fmap f . flip liftM m
Eta expand
(flip liftM m . (.) f) g = (fmap f . flip liftM m) g
flip liftM m (f . g) = fmap f (flip liftM m g)
liftM (f . g) m = fmap f (liftM g m)
This is promising. Take g = id:
liftM (f . id) m = fmap f (liftM id m)
liftM f m = fmap f (liftM id m)
It would suffice to show liftM id = id. That probably follows from its definition:
liftM id m
= m >>= return . id
= m >>= return
= m
Yep! Qed.
edited 2 days ago
Bartosz Milewski
5,36232639
5,36232639
answered Oct 27 at 13:16
luqui
46k6113163
46k6113163
6
Yup. Parametricity means that functions with thefmaptype that takeidtoidare unique, and from the definition ofliftMit follows thatliftM id = id, thereforeliftM = fmap. Cf. my answer to a very similar question.
– duplode
Oct 27 at 15:22
2
So, just to clarify: You can define a monad as a type constructorm, with two polymorphic functions>>=andreturn; and it is automatically a functor, with the action on morphisms defined byliftM. The question is: What if I define another functor, whose action on objects (the type constructorm) is the same, but whose action on morphisms (fmap) is different? You are free to do that in category theory, but if you try to do it in Haskell, you're limited by parametricity, which tells you thatfmapfor a given type constructor is unique, as long as it maps identity to identity.
– Bartosz Milewski
2 days ago
add a comment |
6
Yup. Parametricity means that functions with thefmaptype that takeidtoidare unique, and from the definition ofliftMit follows thatliftM id = id, thereforeliftM = fmap. Cf. my answer to a very similar question.
– duplode
Oct 27 at 15:22
2
So, just to clarify: You can define a monad as a type constructorm, with two polymorphic functions>>=andreturn; and it is automatically a functor, with the action on morphisms defined byliftM. The question is: What if I define another functor, whose action on objects (the type constructorm) is the same, but whose action on morphisms (fmap) is different? You are free to do that in category theory, but if you try to do it in Haskell, you're limited by parametricity, which tells you thatfmapfor a given type constructor is unique, as long as it maps identity to identity.
– Bartosz Milewski
2 days ago
6
6
Yup. Parametricity means that functions with the
fmap type that take id to id are unique, and from the definition of liftM it follows that liftM id = id, therefore liftM = fmap. Cf. my answer to a very similar question.– duplode
Oct 27 at 15:22
Yup. Parametricity means that functions with the
fmap type that take id to id are unique, and from the definition of liftM it follows that liftM id = id, therefore liftM = fmap. Cf. my answer to a very similar question.– duplode
Oct 27 at 15:22
2
2
So, just to clarify: You can define a monad as a type constructor
m, with two polymorphic functions >>= and return; and it is automatically a functor, with the action on morphisms defined by liftM. The question is: What if I define another functor, whose action on objects (the type constructor m) is the same, but whose action on morphisms (fmap) is different? You are free to do that in category theory, but if you try to do it in Haskell, you're limited by parametricity, which tells you that fmap for a given type constructor is unique, as long as it maps identity to identity.– Bartosz Milewski
2 days ago
So, just to clarify: You can define a monad as a type constructor
m, with two polymorphic functions >>= and return; and it is automatically a functor, with the action on morphisms defined by liftM. The question is: What if I define another functor, whose action on objects (the type constructor m) is the same, but whose action on morphisms (fmap) is different? You are free to do that in category theory, but if you try to do it in Haskell, you're limited by parametricity, which tells you that fmap for a given type constructor is unique, as long as it maps identity to identity.– Bartosz Milewski
2 days ago
add a comment |
up vote
6
down vote
For this exercise, I found it easier to work with join rather than >>=. A monad can be equivalently defined through return and join, satisfying
1) join . join = join . fmap join
2) join . return = join . fmap return = id
Indeed, join and >>= are inter-definable:
x >>= f = join (fmap f x)
join x = x >>= id
And the laws you mentioned correspond to those above (I won't prove this).
Then, we have:
liftM f x
= def liftM
x >>= return . f
= def >>=
join (fmap (return . f) x)
= def . and $
join . fmap (return . f) $ x
= fmap law
join . fmap return . fmap f $ x
= join law 2
id . fmap f $ x
= def id, ., $
fmap f x
I am not sure I am satisfied with this, sincefmapappears in the join laws. Imagine back in the days whenFunctorwas not a superclass ofMonad. That is, I suspect "the laws .. correspond to those above" elides some technical dragons which undermine this argument.
– luqui
Oct 27 at 13:20
@luqui I used that to sweep parametricity under the rug :-P. The OP explicitly mentions "It is well known that every monad is also a functor", so I only focused on "real" monads, in the mathematical sense. I actually prefer your approach to mine since it clearly shows parametricity in action, and avoids passing through an equivalent axiomatization.
– chi
Oct 27 at 13:25
2
You are answering a slightly different question. The definition of a monad usingjoinandreturnalso requiresfmap. On the other hand, using those three you can defineliftM. You're showing that thisliftMis the same as the originalfmap. This doesn't require parametricity. It is true in any category.
– Bartosz Milewski
2 days ago
this answer answers the question exactly as asked, "how the equivalence offmapandliftM(defined asliftM f x = x >>= (return . f)) can be derived from [the laws]". the other question answers a wider question, "is the functionliftMwithfmap's type necessarily equivalent tofmap".
– Will Ness
2 days ago
add a comment |
up vote
6
down vote
For this exercise, I found it easier to work with join rather than >>=. A monad can be equivalently defined through return and join, satisfying
1) join . join = join . fmap join
2) join . return = join . fmap return = id
Indeed, join and >>= are inter-definable:
x >>= f = join (fmap f x)
join x = x >>= id
And the laws you mentioned correspond to those above (I won't prove this).
Then, we have:
liftM f x
= def liftM
x >>= return . f
= def >>=
join (fmap (return . f) x)
= def . and $
join . fmap (return . f) $ x
= fmap law
join . fmap return . fmap f $ x
= join law 2
id . fmap f $ x
= def id, ., $
fmap f x
I am not sure I am satisfied with this, sincefmapappears in the join laws. Imagine back in the days whenFunctorwas not a superclass ofMonad. That is, I suspect "the laws .. correspond to those above" elides some technical dragons which undermine this argument.
– luqui
Oct 27 at 13:20
@luqui I used that to sweep parametricity under the rug :-P. The OP explicitly mentions "It is well known that every monad is also a functor", so I only focused on "real" monads, in the mathematical sense. I actually prefer your approach to mine since it clearly shows parametricity in action, and avoids passing through an equivalent axiomatization.
– chi
Oct 27 at 13:25
2
You are answering a slightly different question. The definition of a monad usingjoinandreturnalso requiresfmap. On the other hand, using those three you can defineliftM. You're showing that thisliftMis the same as the originalfmap. This doesn't require parametricity. It is true in any category.
– Bartosz Milewski
2 days ago
this answer answers the question exactly as asked, "how the equivalence offmapandliftM(defined asliftM f x = x >>= (return . f)) can be derived from [the laws]". the other question answers a wider question, "is the functionliftMwithfmap's type necessarily equivalent tofmap".
– Will Ness
2 days ago
add a comment |
up vote
6
down vote
up vote
6
down vote
For this exercise, I found it easier to work with join rather than >>=. A monad can be equivalently defined through return and join, satisfying
1) join . join = join . fmap join
2) join . return = join . fmap return = id
Indeed, join and >>= are inter-definable:
x >>= f = join (fmap f x)
join x = x >>= id
And the laws you mentioned correspond to those above (I won't prove this).
Then, we have:
liftM f x
= def liftM
x >>= return . f
= def >>=
join (fmap (return . f) x)
= def . and $
join . fmap (return . f) $ x
= fmap law
join . fmap return . fmap f $ x
= join law 2
id . fmap f $ x
= def id, ., $
fmap f x
For this exercise, I found it easier to work with join rather than >>=. A monad can be equivalently defined through return and join, satisfying
1) join . join = join . fmap join
2) join . return = join . fmap return = id
Indeed, join and >>= are inter-definable:
x >>= f = join (fmap f x)
join x = x >>= id
And the laws you mentioned correspond to those above (I won't prove this).
Then, we have:
liftM f x
= def liftM
x >>= return . f
= def >>=
join (fmap (return . f) x)
= def . and $
join . fmap (return . f) $ x
= fmap law
join . fmap return . fmap f $ x
= join law 2
id . fmap f $ x
= def id, ., $
fmap f x
answered Oct 27 at 13:12
chi
71.4k279132
71.4k279132
I am not sure I am satisfied with this, sincefmapappears in the join laws. Imagine back in the days whenFunctorwas not a superclass ofMonad. That is, I suspect "the laws .. correspond to those above" elides some technical dragons which undermine this argument.
– luqui
Oct 27 at 13:20
@luqui I used that to sweep parametricity under the rug :-P. The OP explicitly mentions "It is well known that every monad is also a functor", so I only focused on "real" monads, in the mathematical sense. I actually prefer your approach to mine since it clearly shows parametricity in action, and avoids passing through an equivalent axiomatization.
– chi
Oct 27 at 13:25
2
You are answering a slightly different question. The definition of a monad usingjoinandreturnalso requiresfmap. On the other hand, using those three you can defineliftM. You're showing that thisliftMis the same as the originalfmap. This doesn't require parametricity. It is true in any category.
– Bartosz Milewski
2 days ago
this answer answers the question exactly as asked, "how the equivalence offmapandliftM(defined asliftM f x = x >>= (return . f)) can be derived from [the laws]". the other question answers a wider question, "is the functionliftMwithfmap's type necessarily equivalent tofmap".
– Will Ness
2 days ago
add a comment |
I am not sure I am satisfied with this, sincefmapappears in the join laws. Imagine back in the days whenFunctorwas not a superclass ofMonad. That is, I suspect "the laws .. correspond to those above" elides some technical dragons which undermine this argument.
– luqui
Oct 27 at 13:20
@luqui I used that to sweep parametricity under the rug :-P. The OP explicitly mentions "It is well known that every monad is also a functor", so I only focused on "real" monads, in the mathematical sense. I actually prefer your approach to mine since it clearly shows parametricity in action, and avoids passing through an equivalent axiomatization.
– chi
Oct 27 at 13:25
2
You are answering a slightly different question. The definition of a monad usingjoinandreturnalso requiresfmap. On the other hand, using those three you can defineliftM. You're showing that thisliftMis the same as the originalfmap. This doesn't require parametricity. It is true in any category.
– Bartosz Milewski
2 days ago
this answer answers the question exactly as asked, "how the equivalence offmapandliftM(defined asliftM f x = x >>= (return . f)) can be derived from [the laws]". the other question answers a wider question, "is the functionliftMwithfmap's type necessarily equivalent tofmap".
– Will Ness
2 days ago
I am not sure I am satisfied with this, since
fmap appears in the join laws. Imagine back in the days when Functor was not a superclass of Monad. That is, I suspect "the laws .. correspond to those above" elides some technical dragons which undermine this argument.– luqui
Oct 27 at 13:20
I am not sure I am satisfied with this, since
fmap appears in the join laws. Imagine back in the days when Functor was not a superclass of Monad. That is, I suspect "the laws .. correspond to those above" elides some technical dragons which undermine this argument.– luqui
Oct 27 at 13:20
@luqui I used that to sweep parametricity under the rug :-P. The OP explicitly mentions "It is well known that every monad is also a functor", so I only focused on "real" monads, in the mathematical sense. I actually prefer your approach to mine since it clearly shows parametricity in action, and avoids passing through an equivalent axiomatization.
– chi
Oct 27 at 13:25
@luqui I used that to sweep parametricity under the rug :-P. The OP explicitly mentions "It is well known that every monad is also a functor", so I only focused on "real" monads, in the mathematical sense. I actually prefer your approach to mine since it clearly shows parametricity in action, and avoids passing through an equivalent axiomatization.
– chi
Oct 27 at 13:25
2
2
You are answering a slightly different question. The definition of a monad using
join and return also requires fmap. On the other hand, using those three you can define liftM. You're showing that this liftM is the same as the original fmap. This doesn't require parametricity. It is true in any category.– Bartosz Milewski
2 days ago
You are answering a slightly different question. The definition of a monad using
join and return also requires fmap. On the other hand, using those three you can define liftM. You're showing that this liftM is the same as the original fmap. This doesn't require parametricity. It is true in any category.– Bartosz Milewski
2 days ago
this answer answers the question exactly as asked, "how the equivalence of
fmap and liftM (defined as liftM f x = x >>= (return . f)) can be derived from [the laws]". the other question answers a wider question, "is the function liftM with fmap's type necessarily equivalent to fmap".– Will Ness
2 days ago
this answer answers the question exactly as asked, "how the equivalence of
fmap and liftM (defined as liftM f x = x >>= (return . f)) can be derived from [the laws]". the other question answers a wider question, "is the function liftM with fmap's type necessarily equivalent to fmap".– Will Ness
2 days ago
add a comment |
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53022087%2fdo-the-monadic-liftm-and-the-functorial-fmap-have-to-be-equivalent%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password