Can you determine the min or max of a list using only the list monad?









up vote
4
down vote

favorite












Trying to understand the relation between Monad and Foldable. I am aware that that part of the value of the Monad, Applicative and Functor typeclasses is their ability to lift functions over structure, but what if I wanted to generate a summary value (e.g. min or max) for the values contained in a Monad?



This would be impossible without an accumulator right (like in foldable)? And to have an accumulator you have to inject or destroy structure?



min :: Ord a => a -> a -> a

foldMin :: (Foldable t, Ord a) => t a -> Maybe a
foldMin t = foldr go Nothing t
where
go x Nothing = Just x
go x (Just y) = Just (min x y)


Here, the Nothing value is the accumulator. So it would not be possible to do an operation that produces a summary value like this within the confines of a do block?










share|improve this question























  • wat :: [a] -> Maybe a; wat xs = do return (minimum xs)
    – melpomene
    Nov 10 at 3:18














up vote
4
down vote

favorite












Trying to understand the relation between Monad and Foldable. I am aware that that part of the value of the Monad, Applicative and Functor typeclasses is their ability to lift functions over structure, but what if I wanted to generate a summary value (e.g. min or max) for the values contained in a Monad?



This would be impossible without an accumulator right (like in foldable)? And to have an accumulator you have to inject or destroy structure?



min :: Ord a => a -> a -> a

foldMin :: (Foldable t, Ord a) => t a -> Maybe a
foldMin t = foldr go Nothing t
where
go x Nothing = Just x
go x (Just y) = Just (min x y)


Here, the Nothing value is the accumulator. So it would not be possible to do an operation that produces a summary value like this within the confines of a do block?










share|improve this question























  • wat :: [a] -> Maybe a; wat xs = do return (minimum xs)
    – melpomene
    Nov 10 at 3:18












up vote
4
down vote

favorite









up vote
4
down vote

favorite











Trying to understand the relation between Monad and Foldable. I am aware that that part of the value of the Monad, Applicative and Functor typeclasses is their ability to lift functions over structure, but what if I wanted to generate a summary value (e.g. min or max) for the values contained in a Monad?



This would be impossible without an accumulator right (like in foldable)? And to have an accumulator you have to inject or destroy structure?



min :: Ord a => a -> a -> a

foldMin :: (Foldable t, Ord a) => t a -> Maybe a
foldMin t = foldr go Nothing t
where
go x Nothing = Just x
go x (Just y) = Just (min x y)


Here, the Nothing value is the accumulator. So it would not be possible to do an operation that produces a summary value like this within the confines of a do block?










share|improve this question















Trying to understand the relation between Monad and Foldable. I am aware that that part of the value of the Monad, Applicative and Functor typeclasses is their ability to lift functions over structure, but what if I wanted to generate a summary value (e.g. min or max) for the values contained in a Monad?



This would be impossible without an accumulator right (like in foldable)? And to have an accumulator you have to inject or destroy structure?



min :: Ord a => a -> a -> a

foldMin :: (Foldable t, Ord a) => t a -> Maybe a
foldMin t = foldr go Nothing t
where
go x Nothing = Just x
go x (Just y) = Just (min x y)


Here, the Nothing value is the accumulator. So it would not be possible to do an operation that produces a summary value like this within the confines of a do block?







haskell monads foldable






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 10 at 8:06









Mark Seemann

181k33322554




181k33322554










asked Nov 10 at 3:00









Conor Quinn

109113




109113











  • wat :: [a] -> Maybe a; wat xs = do return (minimum xs)
    – melpomene
    Nov 10 at 3:18
















  • wat :: [a] -> Maybe a; wat xs = do return (minimum xs)
    – melpomene
    Nov 10 at 3:18















wat :: [a] -> Maybe a; wat xs = do return (minimum xs)
– melpomene
Nov 10 at 3:18




wat :: [a] -> Maybe a; wat xs = do return (minimum xs)
– melpomene
Nov 10 at 3:18












3 Answers
3






active

oldest

votes

















up vote
3
down vote



accepted










I'm not entirely sure I understand the question, so forgive me if this isn't a useful answer, but as I understand it, the core of the question is this:




So it would not be possible to do an operation that produces a summary value like this within the confines of a do block?




Correct, that would not be possible. Haskell's do notation is syntactic sugar over Monad, so basically syntactic sugar over >>= and return.



return, as you know, doesn't let you 'access' the contents of the Monad, so the only access to the contents you have is via >>=, and in the case of the list monad, for instance, that only gives you one value at a time.



Notice that Foldable doesn't even require that the data container is a Functor (much less a Monad). Famously, Set isn't a Functor instance, but it is a Foldable instance.



You can, for example, find the minimum value in a set:



Prelude Data.Foldable Set> foldr (x -> Just . maybe x (min x)) Nothing $ Set.fromList [42, 1337, 90125, 2112]
Just 42





share|improve this answer





























    up vote
    3
    down vote













    The contrived and inefficient code below is the closest I can get to "using only the list monad". This is probably not what the OP is looking for, but here it is.



    I also exploit head (which you can replace with listToMaybe, if we want totality), and null. I also use empty (which you can replace with ).



    The code works by non deterministically picking an element m and then checking that no greater elements exist. This has a quadratic complexity.



    import Control.Applicative

    maximum :: Ord a => [a] -> a
    maximum xs = head maxima
    where
    isMax m = null $ do
    x <- xs
    if x > m
    then return x
    else empty
    maxima = do
    m <- xs -- non deterministically pick a maximum
    if isMax m
    then return m
    else empty





    share|improve this answer




















    • This is a really cool answer. But yea I meant from a single monadic context (not passing a value into a context), which I now understand is impossible due to the nature of join . fmap
      – Conor Quinn
      Nov 10 at 12:09

















    up vote
    0
    down vote













    I'm also not sure, what the actual question ist, but the need for an accumulator can be hidden with a Monoid instance. Then - for your minimum example - you can use use foldMap from Data.Foldable to map and merge all values of your Foldable. E.g.:



    data Min a = Min getMin :: Maybe a deriving Show

    instance Ord a => Monoid (Min a) where
    mempty = Min Nothing
    mappend a (Min Nothing) = a
    mappend (Min Nothing) b = b
    mappend (Min (Just a)) (Min (Just b)) = Min (Just (min a b))

    foldMin :: (Foldable t, Ord a) => t a -> Maybe a
    foldMin = getMin . foldMap (Min . Just)





    share|improve this answer






















      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%2f53235661%2fcan-you-determine-the-min-or-max-of-a-list-using-only-the-list-monad%23new-answer', 'question_page');

      );

      Post as a guest















      Required, but never shown

























      3 Answers
      3






      active

      oldest

      votes








      3 Answers
      3






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      3
      down vote



      accepted










      I'm not entirely sure I understand the question, so forgive me if this isn't a useful answer, but as I understand it, the core of the question is this:




      So it would not be possible to do an operation that produces a summary value like this within the confines of a do block?




      Correct, that would not be possible. Haskell's do notation is syntactic sugar over Monad, so basically syntactic sugar over >>= and return.



      return, as you know, doesn't let you 'access' the contents of the Monad, so the only access to the contents you have is via >>=, and in the case of the list monad, for instance, that only gives you one value at a time.



      Notice that Foldable doesn't even require that the data container is a Functor (much less a Monad). Famously, Set isn't a Functor instance, but it is a Foldable instance.



      You can, for example, find the minimum value in a set:



      Prelude Data.Foldable Set> foldr (x -> Just . maybe x (min x)) Nothing $ Set.fromList [42, 1337, 90125, 2112]
      Just 42





      share|improve this answer


























        up vote
        3
        down vote



        accepted










        I'm not entirely sure I understand the question, so forgive me if this isn't a useful answer, but as I understand it, the core of the question is this:




        So it would not be possible to do an operation that produces a summary value like this within the confines of a do block?




        Correct, that would not be possible. Haskell's do notation is syntactic sugar over Monad, so basically syntactic sugar over >>= and return.



        return, as you know, doesn't let you 'access' the contents of the Monad, so the only access to the contents you have is via >>=, and in the case of the list monad, for instance, that only gives you one value at a time.



        Notice that Foldable doesn't even require that the data container is a Functor (much less a Monad). Famously, Set isn't a Functor instance, but it is a Foldable instance.



        You can, for example, find the minimum value in a set:



        Prelude Data.Foldable Set> foldr (x -> Just . maybe x (min x)) Nothing $ Set.fromList [42, 1337, 90125, 2112]
        Just 42





        share|improve this answer
























          up vote
          3
          down vote



          accepted







          up vote
          3
          down vote



          accepted






          I'm not entirely sure I understand the question, so forgive me if this isn't a useful answer, but as I understand it, the core of the question is this:




          So it would not be possible to do an operation that produces a summary value like this within the confines of a do block?




          Correct, that would not be possible. Haskell's do notation is syntactic sugar over Monad, so basically syntactic sugar over >>= and return.



          return, as you know, doesn't let you 'access' the contents of the Monad, so the only access to the contents you have is via >>=, and in the case of the list monad, for instance, that only gives you one value at a time.



          Notice that Foldable doesn't even require that the data container is a Functor (much less a Monad). Famously, Set isn't a Functor instance, but it is a Foldable instance.



          You can, for example, find the minimum value in a set:



          Prelude Data.Foldable Set> foldr (x -> Just . maybe x (min x)) Nothing $ Set.fromList [42, 1337, 90125, 2112]
          Just 42





          share|improve this answer














          I'm not entirely sure I understand the question, so forgive me if this isn't a useful answer, but as I understand it, the core of the question is this:




          So it would not be possible to do an operation that produces a summary value like this within the confines of a do block?




          Correct, that would not be possible. Haskell's do notation is syntactic sugar over Monad, so basically syntactic sugar over >>= and return.



          return, as you know, doesn't let you 'access' the contents of the Monad, so the only access to the contents you have is via >>=, and in the case of the list monad, for instance, that only gives you one value at a time.



          Notice that Foldable doesn't even require that the data container is a Functor (much less a Monad). Famously, Set isn't a Functor instance, but it is a Foldable instance.



          You can, for example, find the minimum value in a set:



          Prelude Data.Foldable Set> foldr (x -> Just . maybe x (min x)) Nothing $ Set.fromList [42, 1337, 90125, 2112]
          Just 42






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 10 at 8:27

























          answered Nov 10 at 8:14









          Mark Seemann

          181k33322554




          181k33322554






















              up vote
              3
              down vote













              The contrived and inefficient code below is the closest I can get to "using only the list monad". This is probably not what the OP is looking for, but here it is.



              I also exploit head (which you can replace with listToMaybe, if we want totality), and null. I also use empty (which you can replace with ).



              The code works by non deterministically picking an element m and then checking that no greater elements exist. This has a quadratic complexity.



              import Control.Applicative

              maximum :: Ord a => [a] -> a
              maximum xs = head maxima
              where
              isMax m = null $ do
              x <- xs
              if x > m
              then return x
              else empty
              maxima = do
              m <- xs -- non deterministically pick a maximum
              if isMax m
              then return m
              else empty





              share|improve this answer




















              • This is a really cool answer. But yea I meant from a single monadic context (not passing a value into a context), which I now understand is impossible due to the nature of join . fmap
                – Conor Quinn
                Nov 10 at 12:09














              up vote
              3
              down vote













              The contrived and inefficient code below is the closest I can get to "using only the list monad". This is probably not what the OP is looking for, but here it is.



              I also exploit head (which you can replace with listToMaybe, if we want totality), and null. I also use empty (which you can replace with ).



              The code works by non deterministically picking an element m and then checking that no greater elements exist. This has a quadratic complexity.



              import Control.Applicative

              maximum :: Ord a => [a] -> a
              maximum xs = head maxima
              where
              isMax m = null $ do
              x <- xs
              if x > m
              then return x
              else empty
              maxima = do
              m <- xs -- non deterministically pick a maximum
              if isMax m
              then return m
              else empty





              share|improve this answer




















              • This is a really cool answer. But yea I meant from a single monadic context (not passing a value into a context), which I now understand is impossible due to the nature of join . fmap
                – Conor Quinn
                Nov 10 at 12:09












              up vote
              3
              down vote










              up vote
              3
              down vote









              The contrived and inefficient code below is the closest I can get to "using only the list monad". This is probably not what the OP is looking for, but here it is.



              I also exploit head (which you can replace with listToMaybe, if we want totality), and null. I also use empty (which you can replace with ).



              The code works by non deterministically picking an element m and then checking that no greater elements exist. This has a quadratic complexity.



              import Control.Applicative

              maximum :: Ord a => [a] -> a
              maximum xs = head maxima
              where
              isMax m = null $ do
              x <- xs
              if x > m
              then return x
              else empty
              maxima = do
              m <- xs -- non deterministically pick a maximum
              if isMax m
              then return m
              else empty





              share|improve this answer












              The contrived and inefficient code below is the closest I can get to "using only the list monad". This is probably not what the OP is looking for, but here it is.



              I also exploit head (which you can replace with listToMaybe, if we want totality), and null. I also use empty (which you can replace with ).



              The code works by non deterministically picking an element m and then checking that no greater elements exist. This has a quadratic complexity.



              import Control.Applicative

              maximum :: Ord a => [a] -> a
              maximum xs = head maxima
              where
              isMax m = null $ do
              x <- xs
              if x > m
              then return x
              else empty
              maxima = do
              m <- xs -- non deterministically pick a maximum
              if isMax m
              then return m
              else empty






              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered Nov 10 at 10:58









              chi

              72.1k280133




              72.1k280133











              • This is a really cool answer. But yea I meant from a single monadic context (not passing a value into a context), which I now understand is impossible due to the nature of join . fmap
                – Conor Quinn
                Nov 10 at 12:09
















              • This is a really cool answer. But yea I meant from a single monadic context (not passing a value into a context), which I now understand is impossible due to the nature of join . fmap
                – Conor Quinn
                Nov 10 at 12:09















              This is a really cool answer. But yea I meant from a single monadic context (not passing a value into a context), which I now understand is impossible due to the nature of join . fmap
              – Conor Quinn
              Nov 10 at 12:09




              This is a really cool answer. But yea I meant from a single monadic context (not passing a value into a context), which I now understand is impossible due to the nature of join . fmap
              – Conor Quinn
              Nov 10 at 12:09










              up vote
              0
              down vote













              I'm also not sure, what the actual question ist, but the need for an accumulator can be hidden with a Monoid instance. Then - for your minimum example - you can use use foldMap from Data.Foldable to map and merge all values of your Foldable. E.g.:



              data Min a = Min getMin :: Maybe a deriving Show

              instance Ord a => Monoid (Min a) where
              mempty = Min Nothing
              mappend a (Min Nothing) = a
              mappend (Min Nothing) b = b
              mappend (Min (Just a)) (Min (Just b)) = Min (Just (min a b))

              foldMin :: (Foldable t, Ord a) => t a -> Maybe a
              foldMin = getMin . foldMap (Min . Just)





              share|improve this answer


























                up vote
                0
                down vote













                I'm also not sure, what the actual question ist, but the need for an accumulator can be hidden with a Monoid instance. Then - for your minimum example - you can use use foldMap from Data.Foldable to map and merge all values of your Foldable. E.g.:



                data Min a = Min getMin :: Maybe a deriving Show

                instance Ord a => Monoid (Min a) where
                mempty = Min Nothing
                mappend a (Min Nothing) = a
                mappend (Min Nothing) b = b
                mappend (Min (Just a)) (Min (Just b)) = Min (Just (min a b))

                foldMin :: (Foldable t, Ord a) => t a -> Maybe a
                foldMin = getMin . foldMap (Min . Just)





                share|improve this answer
























                  up vote
                  0
                  down vote










                  up vote
                  0
                  down vote









                  I'm also not sure, what the actual question ist, but the need for an accumulator can be hidden with a Monoid instance. Then - for your minimum example - you can use use foldMap from Data.Foldable to map and merge all values of your Foldable. E.g.:



                  data Min a = Min getMin :: Maybe a deriving Show

                  instance Ord a => Monoid (Min a) where
                  mempty = Min Nothing
                  mappend a (Min Nothing) = a
                  mappend (Min Nothing) b = b
                  mappend (Min (Just a)) (Min (Just b)) = Min (Just (min a b))

                  foldMin :: (Foldable t, Ord a) => t a -> Maybe a
                  foldMin = getMin . foldMap (Min . Just)





                  share|improve this answer














                  I'm also not sure, what the actual question ist, but the need for an accumulator can be hidden with a Monoid instance. Then - for your minimum example - you can use use foldMap from Data.Foldable to map and merge all values of your Foldable. E.g.:



                  data Min a = Min getMin :: Maybe a deriving Show

                  instance Ord a => Monoid (Min a) where
                  mempty = Min Nothing
                  mappend a (Min Nothing) = a
                  mappend (Min Nothing) b = b
                  mappend (Min (Just a)) (Min (Just b)) = Min (Just (min a b))

                  foldMin :: (Foldable t, Ord a) => t a -> Maybe a
                  foldMin = getMin . foldMap (Min . Just)






                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Nov 19 at 19:11

























                  answered Nov 19 at 18:51









                  mschmidt

                  1,93141019




                  1,93141019



























                      draft saved

                      draft discarded
















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid


                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.

                      To learn more, see our tips on writing great answers.





                      Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                      Please pay close attention to the following guidance:


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid


                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.

                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53235661%2fcan-you-determine-the-min-or-max-of-a-list-using-only-the-list-monad%23new-answer', 'question_page');

                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Use pre created SQLite database for Android project in kotlin

                      Darth Vader #20

                      Ondo