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?
haskell monads foldable
add a comment |
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?
haskell monads foldable
wat :: [a] -> Maybe a; wat xs = do return (minimum xs)
– melpomene
Nov 10 at 3:18
add a comment |
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?
haskell monads foldable
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
haskell monads foldable
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
add a comment |
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
add a comment |
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
add a comment |
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
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
add a comment |
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)
add a comment |
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
add a comment |
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
add a comment |
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
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
edited Nov 10 at 8:27
answered Nov 10 at 8:14
Mark Seemann
181k33322554
181k33322554
add a comment |
add a comment |
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
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
add a comment |
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
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
add a comment |
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
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
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
add a comment |
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
add a comment |
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)
add a comment |
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)
add a comment |
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)
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)
edited Nov 19 at 19:11
answered Nov 19 at 18:51
mschmidt
1,93141019
1,93141019
add a comment |
add a comment |
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.
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
Required, but never shown
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
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
Required, but never shown
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
Required, but never shown
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
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
wat :: [a] -> Maybe a; wat xs = do return (minimum xs)
– melpomene
Nov 10 at 3:18