Do the monadic liftM and the functorial fmap have to be equivalent?









up vote
6
down vote

favorite
2












(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 idid


  • fmap f . fmap gfmap (f . g)


  • return x >>= ff x


  • x >>= returnx


  • (x >>= f) >>= gx >>= (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?










share|improve this question

























    up vote
    6
    down vote

    favorite
    2












    (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 idid


    • fmap f . fmap gfmap (f . g)


    • return x >>= ff x


    • x >>= returnx


    • (x >>= f) >>= gx >>= (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?










    share|improve this question























      up vote
      6
      down vote

      favorite
      2









      up vote
      6
      down vote

      favorite
      2






      2





      (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 idid


      • fmap f . fmap gfmap (f . g)


      • return x >>= ff x


      • x >>= returnx


      • (x >>= f) >>= gx >>= (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?










      share|improve this question













      (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 idid


      • fmap f . fmap gfmap (f . g)


      • return x >>= ff x


      • x >>= returnx


      • (x >>= f) >>= gx >>= (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






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Oct 27 at 12:54









      Tom

      2,45312039




      2,45312039






















          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.






          share|improve this answer


















          • 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






          • 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

















          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





          share|improve this answer




















          • 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







          • 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










          • 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










          Your Answer






          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "1"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader:
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          ,
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );













           

          draft saved


          draft discarded


















          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






























          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.






          share|improve this answer


















          • 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






          • 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














          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.






          share|improve this answer


















          • 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






          • 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












          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.






          share|improve this answer














          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.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          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 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




            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












          • 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






          • 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







          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












          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





          share|improve this answer




















          • 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







          • 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










          • 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














          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





          share|improve this answer




















          • 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







          • 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










          • 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












          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





          share|improve this answer












          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






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Oct 27 at 13:12









          chi

          71.4k279132




          71.4k279132











          • 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







          • 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










          • 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
















          • 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







          • 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










          • 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















          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

















           

          draft saved


          draft discarded















































           


          draft saved


          draft discarded














          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














































































          這個網誌中的熱門文章

          Barbados

          How to read a connectionString WITH PROVIDER in .NET Core?

          Node.js Script on GitHub Pages or Amazon S3