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
≡id
fmap f . fmap g
≡fmap (f . g)
return x >>= f
≡f x
x >>= 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
≡id
fmap f . fmap g
≡fmap (f . g)
return x >>= f
≡f x
x >>= 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
≡id
fmap f . fmap g
≡fmap (f . g)
return x >>= f
≡f x
x >>= 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
≡id
fmap f . fmap g
≡fmap (f . g)
return x >>= f
≡f x
x >>= 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 thefmap
type that takeid
toid
are unique, and from the definition ofliftM
it 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 thatfmap
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, sincefmap
appears in the join laws. Imagine back in the days whenFunctor
was 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 usingjoin
andreturn
also requiresfmap
. On the other hand, using those three you can defineliftM
. You're showing that thisliftM
is 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 offmap
andliftM
(defined asliftM f x = x >>= (return . f)
) can be derived from [the laws]". the other question answers a wider question, "is the functionliftM
withfmap
'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 thefmap
type that takeid
toid
are unique, and from the definition ofliftM
it 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 thatfmap
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
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 thefmap
type that takeid
toid
are unique, and from the definition ofliftM
it 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 thatfmap
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
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 thefmap
type that takeid
toid
are unique, and from the definition ofliftM
it 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 thatfmap
for 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 thefmap
type that takeid
toid
are unique, and from the definition ofliftM
it 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 thatfmap
for 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, sincefmap
appears in the join laws. Imagine back in the days whenFunctor
was 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 usingjoin
andreturn
also requiresfmap
. On the other hand, using those three you can defineliftM
. You're showing that thisliftM
is 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 offmap
andliftM
(defined asliftM f x = x >>= (return . f)
) can be derived from [the laws]". the other question answers a wider question, "is the functionliftM
withfmap
'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, sincefmap
appears in the join laws. Imagine back in the days whenFunctor
was 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 usingjoin
andreturn
also requiresfmap
. On the other hand, using those three you can defineliftM
. You're showing that thisliftM
is 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 offmap
andliftM
(defined asliftM f x = x >>= (return . f)
) can be derived from [the laws]". the other question answers a wider question, "is the functionliftM
withfmap
'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, sincefmap
appears in the join laws. Imagine back in the days whenFunctor
was 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 usingjoin
andreturn
also requiresfmap
. On the other hand, using those three you can defineliftM
. You're showing that thisliftM
is 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 offmap
andliftM
(defined asliftM f x = x >>= (return . f)
) can be derived from [the laws]". the other question answers a wider question, "is the functionliftM
withfmap
's type necessarily equivalent tofmap
".
– Will Ness
2 days ago
add a comment |
I am not sure I am satisfied with this, sincefmap
appears in the join laws. Imagine back in the days whenFunctor
was 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 usingjoin
andreturn
also requiresfmap
. On the other hand, using those three you can defineliftM
. You're showing that thisliftM
is 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 offmap
andliftM
(defined asliftM f x = x >>= (return . f)
) can be derived from [the laws]". the other question answers a wider question, "is the functionliftM
withfmap
'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