List comprehension guard equivalent of filterMHaskell List Comprehensions guards in F#haskell - let/where equivalent within list comprehension?Haskell: Lists, Arrays, Vectors, SequencesFor a list comprehension in Haskell the equivalent in Scala?Using guards in list comprehensionsWhat are some better ways to write [(-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1)] in Haskell?List comprehension guardsGetting my bearings on state-monadic “uncurrying”Combining elements with probabilities in HaskellGuards in list comprehensions don't terminate infinite lists?

What would the EU’s position be with respect to a United Ireland?

What is the difference between increasing volume and increasing gain?

Can I return my ability to cast Wish by using Glyph of warding?

Found a minor bug, affecting 1% of users. What should QA do?

Anonymous reviewer disclosed his identity. Should I thank him by name?

Can an NPC use the teleport spell to affect an object they can see with the scry spell?

"cd" into /sys/kernel/debug/tracing causes permission change

Could Boris Johnson face criminal charges for illegally proroguing Parliament?

What is the origin of the minced oath “Jiminy”?

"Categorical" Schröder–Bernstein theorem?

In search of a pedagogically simple example of asymmetric encryption routine?

What does a textbook look like while you are writing it?

Sum of series with addition

Determine the Winner of a Game of Australian Football

How to catch creatures that can predict the next few minutes?

Is American Sign Language phonetic?

The answer is the same (tricky puzzle!)

Why is the time of useful consciousness only seconds at high altitudes?

Colleague's grant application resembles my PhD thesis

I've been fired, was allowed to announce it as if I quit and given extra notice, how to handle the questions?

Why do many websites hide input when entering a OTP

Did Joe Biden "stop a prosecution" into his son in Ukraine? And did he brag about stopping the prosecution?

How is the speed of nucleons in the nucleus measured?

How to "Start as close to the end as possible", and why to do so?



List comprehension guard equivalent of filterM


Haskell List Comprehensions guards in F#haskell - let/where equivalent within list comprehension?Haskell: Lists, Arrays, Vectors, SequencesFor a list comprehension in Haskell the equivalent in Scala?Using guards in list comprehensionsWhat are some better ways to write [(-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1)] in Haskell?List comprehension guardsGetting my bearings on state-monadic “uncurrying”Combining elements with probabilities in HaskellGuards in list comprehensions don't terminate infinite lists?






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty
margin-bottom:0;









1















List comprehensions have overlapping functionality with map and filter. filterM caters for the situation in which the predicate returns a Bool wrapped in a monad (well, an Applicative, to be precise). mapM does something similar for mapping functions whose result is wrapped in an Applicative.



In case you want to reproduce the behaviour of mapM with a list comprehension, sequence comes to the rescue. But how can filterM be replaced with a list comprehension? In other words, how can a predicate which returns a Bool inside a context, be used as a guard in list comprehensions?



Below are trivial examples exploring the 2x2x2 space (filter/map, function/comprehension, plain/monadic) of above observations, only I don't know how to write fcm. How can fcm be fixed so that it has the same value as ffm?



import Control.Monad (filterM)

predicate = (>3)
convert = (*10)
predicateM = Just . predicate -- Just represents an arbitrary monad
convertM = Just . convert
data_ = [1..5]

ffp = filter predicate data_
ffm = filterM predicateM data_
fcp = [a | a <- data_, predicate a]
fcm = [a | a <- data_, predicateM a]

mfp = map convert data_
mfm = mapM convertM data_
mcp = [ convert a | a <- data_ ]
mcm = sequence [ convertM a | a <- data_ ]


Edit:



It's important to note that the versions whose name ends in m must use a convertM or predicateM: the plain convert and predicate are unavailable in those situations; that's the whole point of the question.



Background information



The motivation arises from having a bunch of functions (here is a simplified collection, which is hopefully representative)



convert :: a -> r -> b
predicate :: a -> r -> Bool
big :: [a] -> r -> [b]

big as r = [ convert a r | a <- as, predicate a r ]


which are begging to be refactored in terms of Reader ... and one of which (big) uses one of the others (predicate) as a predicate in listcomp guard.



Refactoring works just fine, as long as the listcomp is replaced with a combination of mapM and filterM:



convertR :: a -> Reader r b
predicateR :: a -> Reader r Bool
bigR :: [a] -> Reader r [b]

bigR as = mapM convertR =<< filterM predicateR as


The trouble with this is that, in real life, the listcomp is much more complex, and the translation to mapM and filterM is far less clean.



Hence the motivation for wanting to keep the listcomp even when the predicate has turned monadic.



Edit 2



The real listcomp is more complex, because it combines elements from more than one list. I've tried to extact the essence of the problem into the following example, which differs from Edit 1 in that



  • The listcomp in big takes data from more than one list.


  • predicate takes more than one value as input.


  • convert has been rename to combine and takes more than one value as input.

  • Similar changes for the Reader versions.

.



combine :: r -> (a,a) -> b
predicate :: r -> (a,a) -> Bool
big, big' :: r -> [a] -> [b]

big r as = [ combine r (a,b) | a <- as, b <- as, predicate r (a,b) ]
big' r as = map (combine r) $ filter (predicate r) $ [ (a,b) | a <- as, b <- as ]

combineR :: (a,a) -> Reader r b
predicateR :: (a,a) -> Reader r Bool
bigR, bigR' :: [a] -> Reader r [b]

bigR = undefined
bigR' as = mapM combineR =<< filterM predicateR =<< return [ (a,b) | a <- as, b <- as ]


big' is a rewrite of big in which combine and predicate are extracted from the listcomp. This has a direct equivalent in the Reader version: bigR'. So, the question is, how can you write bigR which should be



  1. Not significantly uglier than bigR'

  2. As direct a translation of big as reasonably possible.

At this stage I'm tempted to conclude that bigR' is as good as it's going to get. This implies that the answer to my question is:



  • keep the listcomp for constructing the cartesian product

  • move predicate and combine out of the expression into a filter and a map respectively

  • in the monadic version, replace filter and map with filterM and mapM (and $ with =<<).

  • uncurry the predicate and combiner functions: the listcomp works equally well with curried and uncurried versions, but the map-filter combination needs them to be curried. At this stage this is probably the biggest price to pay for losing the ability to use the listcomp.









share|improve this question


























  • isn't it just fcm = Just [a | a <- data_, predicate a]? (It can't result in a Nothing because (Just . predicate) doesn't ever.)

    – Robin Zigmond
    Mar 28 at 16:07











  • @RobinZigmond The m in fcm indicates that the predicate returns m Bool. By changing (Just . predicate) to predicate you've moved from the fcm corner of the cube to the fcp corner. The whole point is that, for whatever reason, the predicate returns a monad, and I don't have the option of changing that, I just have to deal with it. (In real life this came up when refactoring a bunch of functions into the Reader monad, and suddenly my predicate turned monadic and my lisctomp broke.)

    – jacg
    Mar 28 at 16:18











  • but a predicate by definition cannot return m Bool. It must return a Bool. You're thinking of the fact that the function argument to filterM is of type a -> m Bool, but you can't use that in a list comprehension because it's not actually a predicate. I thought the aim for fcm was for it to produce the same result as ffm but using a list comp - what I've put above is the only way I see to do it.

    – Robin Zigmond
    Mar 28 at 16:21











  • @RobinZigmond As I said, this is motivated by refactoring to Reader. Imagine you have fcm :: [a] -> r -> [b] and p :: a -> r -> Bool. fcm a r = [ xxx a r | a <- as , p a r]. Then you try to refactor to fcm :: [a] -> Reader r [b]` and p :: a -> Reader r Bool, which makes p unusable in the listcomp. Changing xxx from a -> r ->b to a -> Reader r b can be dealt with either by switching to mapM or using sequence with the listcomp. I can see how to deal with the change in p by replacing the listcomp with filterM, but can it be done without getting rid of the listcomp?

    – jacg
    Mar 28 at 16:38











  • @RobinZigmond Yes, fcm is supposed to produce the same result as ffm using a listcomp ... while respecting the fact that the only function you had to supply filterM has type a -> m Bool. (Just . predicate) represents the function I have to work with. I do not have the luxury of removing the Just .

    – jacg
    Mar 28 at 16:47

















1















List comprehensions have overlapping functionality with map and filter. filterM caters for the situation in which the predicate returns a Bool wrapped in a monad (well, an Applicative, to be precise). mapM does something similar for mapping functions whose result is wrapped in an Applicative.



In case you want to reproduce the behaviour of mapM with a list comprehension, sequence comes to the rescue. But how can filterM be replaced with a list comprehension? In other words, how can a predicate which returns a Bool inside a context, be used as a guard in list comprehensions?



Below are trivial examples exploring the 2x2x2 space (filter/map, function/comprehension, plain/monadic) of above observations, only I don't know how to write fcm. How can fcm be fixed so that it has the same value as ffm?



import Control.Monad (filterM)

predicate = (>3)
convert = (*10)
predicateM = Just . predicate -- Just represents an arbitrary monad
convertM = Just . convert
data_ = [1..5]

ffp = filter predicate data_
ffm = filterM predicateM data_
fcp = [a | a <- data_, predicate a]
fcm = [a | a <- data_, predicateM a]

mfp = map convert data_
mfm = mapM convertM data_
mcp = [ convert a | a <- data_ ]
mcm = sequence [ convertM a | a <- data_ ]


Edit:



It's important to note that the versions whose name ends in m must use a convertM or predicateM: the plain convert and predicate are unavailable in those situations; that's the whole point of the question.



Background information



The motivation arises from having a bunch of functions (here is a simplified collection, which is hopefully representative)



convert :: a -> r -> b
predicate :: a -> r -> Bool
big :: [a] -> r -> [b]

big as r = [ convert a r | a <- as, predicate a r ]


which are begging to be refactored in terms of Reader ... and one of which (big) uses one of the others (predicate) as a predicate in listcomp guard.



Refactoring works just fine, as long as the listcomp is replaced with a combination of mapM and filterM:



convertR :: a -> Reader r b
predicateR :: a -> Reader r Bool
bigR :: [a] -> Reader r [b]

bigR as = mapM convertR =<< filterM predicateR as


The trouble with this is that, in real life, the listcomp is much more complex, and the translation to mapM and filterM is far less clean.



Hence the motivation for wanting to keep the listcomp even when the predicate has turned monadic.



Edit 2



The real listcomp is more complex, because it combines elements from more than one list. I've tried to extact the essence of the problem into the following example, which differs from Edit 1 in that



  • The listcomp in big takes data from more than one list.


  • predicate takes more than one value as input.


  • convert has been rename to combine and takes more than one value as input.

  • Similar changes for the Reader versions.

.



combine :: r -> (a,a) -> b
predicate :: r -> (a,a) -> Bool
big, big' :: r -> [a] -> [b]

big r as = [ combine r (a,b) | a <- as, b <- as, predicate r (a,b) ]
big' r as = map (combine r) $ filter (predicate r) $ [ (a,b) | a <- as, b <- as ]

combineR :: (a,a) -> Reader r b
predicateR :: (a,a) -> Reader r Bool
bigR, bigR' :: [a] -> Reader r [b]

bigR = undefined
bigR' as = mapM combineR =<< filterM predicateR =<< return [ (a,b) | a <- as, b <- as ]


big' is a rewrite of big in which combine and predicate are extracted from the listcomp. This has a direct equivalent in the Reader version: bigR'. So, the question is, how can you write bigR which should be



  1. Not significantly uglier than bigR'

  2. As direct a translation of big as reasonably possible.

At this stage I'm tempted to conclude that bigR' is as good as it's going to get. This implies that the answer to my question is:



  • keep the listcomp for constructing the cartesian product

  • move predicate and combine out of the expression into a filter and a map respectively

  • in the monadic version, replace filter and map with filterM and mapM (and $ with =<<).

  • uncurry the predicate and combiner functions: the listcomp works equally well with curried and uncurried versions, but the map-filter combination needs them to be curried. At this stage this is probably the biggest price to pay for losing the ability to use the listcomp.









share|improve this question


























  • isn't it just fcm = Just [a | a <- data_, predicate a]? (It can't result in a Nothing because (Just . predicate) doesn't ever.)

    – Robin Zigmond
    Mar 28 at 16:07











  • @RobinZigmond The m in fcm indicates that the predicate returns m Bool. By changing (Just . predicate) to predicate you've moved from the fcm corner of the cube to the fcp corner. The whole point is that, for whatever reason, the predicate returns a monad, and I don't have the option of changing that, I just have to deal with it. (In real life this came up when refactoring a bunch of functions into the Reader monad, and suddenly my predicate turned monadic and my lisctomp broke.)

    – jacg
    Mar 28 at 16:18











  • but a predicate by definition cannot return m Bool. It must return a Bool. You're thinking of the fact that the function argument to filterM is of type a -> m Bool, but you can't use that in a list comprehension because it's not actually a predicate. I thought the aim for fcm was for it to produce the same result as ffm but using a list comp - what I've put above is the only way I see to do it.

    – Robin Zigmond
    Mar 28 at 16:21











  • @RobinZigmond As I said, this is motivated by refactoring to Reader. Imagine you have fcm :: [a] -> r -> [b] and p :: a -> r -> Bool. fcm a r = [ xxx a r | a <- as , p a r]. Then you try to refactor to fcm :: [a] -> Reader r [b]` and p :: a -> Reader r Bool, which makes p unusable in the listcomp. Changing xxx from a -> r ->b to a -> Reader r b can be dealt with either by switching to mapM or using sequence with the listcomp. I can see how to deal with the change in p by replacing the listcomp with filterM, but can it be done without getting rid of the listcomp?

    – jacg
    Mar 28 at 16:38











  • @RobinZigmond Yes, fcm is supposed to produce the same result as ffm using a listcomp ... while respecting the fact that the only function you had to supply filterM has type a -> m Bool. (Just . predicate) represents the function I have to work with. I do not have the luxury of removing the Just .

    – jacg
    Mar 28 at 16:47













1












1








1








List comprehensions have overlapping functionality with map and filter. filterM caters for the situation in which the predicate returns a Bool wrapped in a monad (well, an Applicative, to be precise). mapM does something similar for mapping functions whose result is wrapped in an Applicative.



In case you want to reproduce the behaviour of mapM with a list comprehension, sequence comes to the rescue. But how can filterM be replaced with a list comprehension? In other words, how can a predicate which returns a Bool inside a context, be used as a guard in list comprehensions?



Below are trivial examples exploring the 2x2x2 space (filter/map, function/comprehension, plain/monadic) of above observations, only I don't know how to write fcm. How can fcm be fixed so that it has the same value as ffm?



import Control.Monad (filterM)

predicate = (>3)
convert = (*10)
predicateM = Just . predicate -- Just represents an arbitrary monad
convertM = Just . convert
data_ = [1..5]

ffp = filter predicate data_
ffm = filterM predicateM data_
fcp = [a | a <- data_, predicate a]
fcm = [a | a <- data_, predicateM a]

mfp = map convert data_
mfm = mapM convertM data_
mcp = [ convert a | a <- data_ ]
mcm = sequence [ convertM a | a <- data_ ]


Edit:



It's important to note that the versions whose name ends in m must use a convertM or predicateM: the plain convert and predicate are unavailable in those situations; that's the whole point of the question.



Background information



The motivation arises from having a bunch of functions (here is a simplified collection, which is hopefully representative)



convert :: a -> r -> b
predicate :: a -> r -> Bool
big :: [a] -> r -> [b]

big as r = [ convert a r | a <- as, predicate a r ]


which are begging to be refactored in terms of Reader ... and one of which (big) uses one of the others (predicate) as a predicate in listcomp guard.



Refactoring works just fine, as long as the listcomp is replaced with a combination of mapM and filterM:



convertR :: a -> Reader r b
predicateR :: a -> Reader r Bool
bigR :: [a] -> Reader r [b]

bigR as = mapM convertR =<< filterM predicateR as


The trouble with this is that, in real life, the listcomp is much more complex, and the translation to mapM and filterM is far less clean.



Hence the motivation for wanting to keep the listcomp even when the predicate has turned monadic.



Edit 2



The real listcomp is more complex, because it combines elements from more than one list. I've tried to extact the essence of the problem into the following example, which differs from Edit 1 in that



  • The listcomp in big takes data from more than one list.


  • predicate takes more than one value as input.


  • convert has been rename to combine and takes more than one value as input.

  • Similar changes for the Reader versions.

.



combine :: r -> (a,a) -> b
predicate :: r -> (a,a) -> Bool
big, big' :: r -> [a] -> [b]

big r as = [ combine r (a,b) | a <- as, b <- as, predicate r (a,b) ]
big' r as = map (combine r) $ filter (predicate r) $ [ (a,b) | a <- as, b <- as ]

combineR :: (a,a) -> Reader r b
predicateR :: (a,a) -> Reader r Bool
bigR, bigR' :: [a] -> Reader r [b]

bigR = undefined
bigR' as = mapM combineR =<< filterM predicateR =<< return [ (a,b) | a <- as, b <- as ]


big' is a rewrite of big in which combine and predicate are extracted from the listcomp. This has a direct equivalent in the Reader version: bigR'. So, the question is, how can you write bigR which should be



  1. Not significantly uglier than bigR'

  2. As direct a translation of big as reasonably possible.

At this stage I'm tempted to conclude that bigR' is as good as it's going to get. This implies that the answer to my question is:



  • keep the listcomp for constructing the cartesian product

  • move predicate and combine out of the expression into a filter and a map respectively

  • in the monadic version, replace filter and map with filterM and mapM (and $ with =<<).

  • uncurry the predicate and combiner functions: the listcomp works equally well with curried and uncurried versions, but the map-filter combination needs them to be curried. At this stage this is probably the biggest price to pay for losing the ability to use the listcomp.









share|improve this question
















List comprehensions have overlapping functionality with map and filter. filterM caters for the situation in which the predicate returns a Bool wrapped in a monad (well, an Applicative, to be precise). mapM does something similar for mapping functions whose result is wrapped in an Applicative.



In case you want to reproduce the behaviour of mapM with a list comprehension, sequence comes to the rescue. But how can filterM be replaced with a list comprehension? In other words, how can a predicate which returns a Bool inside a context, be used as a guard in list comprehensions?



Below are trivial examples exploring the 2x2x2 space (filter/map, function/comprehension, plain/monadic) of above observations, only I don't know how to write fcm. How can fcm be fixed so that it has the same value as ffm?



import Control.Monad (filterM)

predicate = (>3)
convert = (*10)
predicateM = Just . predicate -- Just represents an arbitrary monad
convertM = Just . convert
data_ = [1..5]

ffp = filter predicate data_
ffm = filterM predicateM data_
fcp = [a | a <- data_, predicate a]
fcm = [a | a <- data_, predicateM a]

mfp = map convert data_
mfm = mapM convertM data_
mcp = [ convert a | a <- data_ ]
mcm = sequence [ convertM a | a <- data_ ]


Edit:



It's important to note that the versions whose name ends in m must use a convertM or predicateM: the plain convert and predicate are unavailable in those situations; that's the whole point of the question.



Background information



The motivation arises from having a bunch of functions (here is a simplified collection, which is hopefully representative)



convert :: a -> r -> b
predicate :: a -> r -> Bool
big :: [a] -> r -> [b]

big as r = [ convert a r | a <- as, predicate a r ]


which are begging to be refactored in terms of Reader ... and one of which (big) uses one of the others (predicate) as a predicate in listcomp guard.



Refactoring works just fine, as long as the listcomp is replaced with a combination of mapM and filterM:



convertR :: a -> Reader r b
predicateR :: a -> Reader r Bool
bigR :: [a] -> Reader r [b]

bigR as = mapM convertR =<< filterM predicateR as


The trouble with this is that, in real life, the listcomp is much more complex, and the translation to mapM and filterM is far less clean.



Hence the motivation for wanting to keep the listcomp even when the predicate has turned monadic.



Edit 2



The real listcomp is more complex, because it combines elements from more than one list. I've tried to extact the essence of the problem into the following example, which differs from Edit 1 in that



  • The listcomp in big takes data from more than one list.


  • predicate takes more than one value as input.


  • convert has been rename to combine and takes more than one value as input.

  • Similar changes for the Reader versions.

.



combine :: r -> (a,a) -> b
predicate :: r -> (a,a) -> Bool
big, big' :: r -> [a] -> [b]

big r as = [ combine r (a,b) | a <- as, b <- as, predicate r (a,b) ]
big' r as = map (combine r) $ filter (predicate r) $ [ (a,b) | a <- as, b <- as ]

combineR :: (a,a) -> Reader r b
predicateR :: (a,a) -> Reader r Bool
bigR, bigR' :: [a] -> Reader r [b]

bigR = undefined
bigR' as = mapM combineR =<< filterM predicateR =<< return [ (a,b) | a <- as, b <- as ]


big' is a rewrite of big in which combine and predicate are extracted from the listcomp. This has a direct equivalent in the Reader version: bigR'. So, the question is, how can you write bigR which should be



  1. Not significantly uglier than bigR'

  2. As direct a translation of big as reasonably possible.

At this stage I'm tempted to conclude that bigR' is as good as it's going to get. This implies that the answer to my question is:



  • keep the listcomp for constructing the cartesian product

  • move predicate and combine out of the expression into a filter and a map respectively

  • in the monadic version, replace filter and map with filterM and mapM (and $ with =<<).

  • uncurry the predicate and combiner functions: the listcomp works equally well with curried and uncurried versions, but the map-filter combination needs them to be curried. At this stage this is probably the biggest price to pay for losing the ability to use the listcomp.






haskell






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Mar 29 at 12:45







jacg

















asked Mar 28 at 15:52









jacgjacg

1,2086 silver badges19 bronze badges




1,2086 silver badges19 bronze badges















  • isn't it just fcm = Just [a | a <- data_, predicate a]? (It can't result in a Nothing because (Just . predicate) doesn't ever.)

    – Robin Zigmond
    Mar 28 at 16:07











  • @RobinZigmond The m in fcm indicates that the predicate returns m Bool. By changing (Just . predicate) to predicate you've moved from the fcm corner of the cube to the fcp corner. The whole point is that, for whatever reason, the predicate returns a monad, and I don't have the option of changing that, I just have to deal with it. (In real life this came up when refactoring a bunch of functions into the Reader monad, and suddenly my predicate turned monadic and my lisctomp broke.)

    – jacg
    Mar 28 at 16:18











  • but a predicate by definition cannot return m Bool. It must return a Bool. You're thinking of the fact that the function argument to filterM is of type a -> m Bool, but you can't use that in a list comprehension because it's not actually a predicate. I thought the aim for fcm was for it to produce the same result as ffm but using a list comp - what I've put above is the only way I see to do it.

    – Robin Zigmond
    Mar 28 at 16:21











  • @RobinZigmond As I said, this is motivated by refactoring to Reader. Imagine you have fcm :: [a] -> r -> [b] and p :: a -> r -> Bool. fcm a r = [ xxx a r | a <- as , p a r]. Then you try to refactor to fcm :: [a] -> Reader r [b]` and p :: a -> Reader r Bool, which makes p unusable in the listcomp. Changing xxx from a -> r ->b to a -> Reader r b can be dealt with either by switching to mapM or using sequence with the listcomp. I can see how to deal with the change in p by replacing the listcomp with filterM, but can it be done without getting rid of the listcomp?

    – jacg
    Mar 28 at 16:38











  • @RobinZigmond Yes, fcm is supposed to produce the same result as ffm using a listcomp ... while respecting the fact that the only function you had to supply filterM has type a -> m Bool. (Just . predicate) represents the function I have to work with. I do not have the luxury of removing the Just .

    – jacg
    Mar 28 at 16:47

















  • isn't it just fcm = Just [a | a <- data_, predicate a]? (It can't result in a Nothing because (Just . predicate) doesn't ever.)

    – Robin Zigmond
    Mar 28 at 16:07











  • @RobinZigmond The m in fcm indicates that the predicate returns m Bool. By changing (Just . predicate) to predicate you've moved from the fcm corner of the cube to the fcp corner. The whole point is that, for whatever reason, the predicate returns a monad, and I don't have the option of changing that, I just have to deal with it. (In real life this came up when refactoring a bunch of functions into the Reader monad, and suddenly my predicate turned monadic and my lisctomp broke.)

    – jacg
    Mar 28 at 16:18











  • but a predicate by definition cannot return m Bool. It must return a Bool. You're thinking of the fact that the function argument to filterM is of type a -> m Bool, but you can't use that in a list comprehension because it's not actually a predicate. I thought the aim for fcm was for it to produce the same result as ffm but using a list comp - what I've put above is the only way I see to do it.

    – Robin Zigmond
    Mar 28 at 16:21











  • @RobinZigmond As I said, this is motivated by refactoring to Reader. Imagine you have fcm :: [a] -> r -> [b] and p :: a -> r -> Bool. fcm a r = [ xxx a r | a <- as , p a r]. Then you try to refactor to fcm :: [a] -> Reader r [b]` and p :: a -> Reader r Bool, which makes p unusable in the listcomp. Changing xxx from a -> r ->b to a -> Reader r b can be dealt with either by switching to mapM or using sequence with the listcomp. I can see how to deal with the change in p by replacing the listcomp with filterM, but can it be done without getting rid of the listcomp?

    – jacg
    Mar 28 at 16:38











  • @RobinZigmond Yes, fcm is supposed to produce the same result as ffm using a listcomp ... while respecting the fact that the only function you had to supply filterM has type a -> m Bool. (Just . predicate) represents the function I have to work with. I do not have the luxury of removing the Just .

    – jacg
    Mar 28 at 16:47
















isn't it just fcm = Just [a | a <- data_, predicate a]? (It can't result in a Nothing because (Just . predicate) doesn't ever.)

– Robin Zigmond
Mar 28 at 16:07





isn't it just fcm = Just [a | a <- data_, predicate a]? (It can't result in a Nothing because (Just . predicate) doesn't ever.)

– Robin Zigmond
Mar 28 at 16:07













@RobinZigmond The m in fcm indicates that the predicate returns m Bool. By changing (Just . predicate) to predicate you've moved from the fcm corner of the cube to the fcp corner. The whole point is that, for whatever reason, the predicate returns a monad, and I don't have the option of changing that, I just have to deal with it. (In real life this came up when refactoring a bunch of functions into the Reader monad, and suddenly my predicate turned monadic and my lisctomp broke.)

– jacg
Mar 28 at 16:18





@RobinZigmond The m in fcm indicates that the predicate returns m Bool. By changing (Just . predicate) to predicate you've moved from the fcm corner of the cube to the fcp corner. The whole point is that, for whatever reason, the predicate returns a monad, and I don't have the option of changing that, I just have to deal with it. (In real life this came up when refactoring a bunch of functions into the Reader monad, and suddenly my predicate turned monadic and my lisctomp broke.)

– jacg
Mar 28 at 16:18













but a predicate by definition cannot return m Bool. It must return a Bool. You're thinking of the fact that the function argument to filterM is of type a -> m Bool, but you can't use that in a list comprehension because it's not actually a predicate. I thought the aim for fcm was for it to produce the same result as ffm but using a list comp - what I've put above is the only way I see to do it.

– Robin Zigmond
Mar 28 at 16:21





but a predicate by definition cannot return m Bool. It must return a Bool. You're thinking of the fact that the function argument to filterM is of type a -> m Bool, but you can't use that in a list comprehension because it's not actually a predicate. I thought the aim for fcm was for it to produce the same result as ffm but using a list comp - what I've put above is the only way I see to do it.

– Robin Zigmond
Mar 28 at 16:21













@RobinZigmond As I said, this is motivated by refactoring to Reader. Imagine you have fcm :: [a] -> r -> [b] and p :: a -> r -> Bool. fcm a r = [ xxx a r | a <- as , p a r]. Then you try to refactor to fcm :: [a] -> Reader r [b]` and p :: a -> Reader r Bool, which makes p unusable in the listcomp. Changing xxx from a -> r ->b to a -> Reader r b can be dealt with either by switching to mapM or using sequence with the listcomp. I can see how to deal with the change in p by replacing the listcomp with filterM, but can it be done without getting rid of the listcomp?

– jacg
Mar 28 at 16:38





@RobinZigmond As I said, this is motivated by refactoring to Reader. Imagine you have fcm :: [a] -> r -> [b] and p :: a -> r -> Bool. fcm a r = [ xxx a r | a <- as , p a r]. Then you try to refactor to fcm :: [a] -> Reader r [b]` and p :: a -> Reader r Bool, which makes p unusable in the listcomp. Changing xxx from a -> r ->b to a -> Reader r b can be dealt with either by switching to mapM or using sequence with the listcomp. I can see how to deal with the change in p by replacing the listcomp with filterM, but can it be done without getting rid of the listcomp?

– jacg
Mar 28 at 16:38













@RobinZigmond Yes, fcm is supposed to produce the same result as ffm using a listcomp ... while respecting the fact that the only function you had to supply filterM has type a -> m Bool. (Just . predicate) represents the function I have to work with. I do not have the luxury of removing the Just .

– jacg
Mar 28 at 16:47





@RobinZigmond Yes, fcm is supposed to produce the same result as ffm using a listcomp ... while respecting the fact that the only function you had to supply filterM has type a -> m Bool. (Just . predicate) represents the function I have to work with. I do not have the luxury of removing the Just .

– jacg
Mar 28 at 16:47












2 Answers
2






active

oldest

votes


















1
















Personally, I can't figure out a way to do it with just a list comp, but this might get you closer? (I've listed some intermediate steps I went through so you can take it in a different direction if you need).



-# LANGUAGE MonadComprehensions #-

predicateM = return . (>3)
[[a | True <- predicateM a] | a <- [1,2,3,4,5]]
:: (Num b, Ord b, Control.Monad.Fail.MonadFail m) => [m b]
[[if b then Just a else Nothing | b <- predicateM a] | a <- [1,2,3,4,5]]
:: (Num a, Monad m, Ord a) => [m (Maybe a)]
[[bool Nothing (Just a) b | b <- predicateM a] | a <- [1,2,3,4,5]]
:: (Num a, Monad m, Ord a) => [m (Maybe a)]
catMaybes <$> sequence [[bool Nothing (Just a) b | b <- predicateM a] | a <- [1,2,3,4,5]]
:: (Monad f, Num a, Ord a) => f [a]

filterM' p xs = catMaybes <$> sequence [[bool Nothing (Just a) b | b <- p a] | a <- xs]


There may be something neater with a ListT?



EDIT: Another approach, although it spews some warnings about ListT giving unlawful instances..



unListT (ListT x) = x
filterM'' p xs = unListT [a | (a,True) <- ListT $ mapM (x -> return . (x,) =<< p x) xs]


EDIT2: Okay I got it down to a single comprehension!



filterM''' :: (Traversable m1, Monad m2, Monad m1, Alternative m1) => (b -> m2 Bool) -> m1 b -> m2 (m1 b)
filterM''' p xs = [[a | (a,b) <- mlist, b] | mlist <- mapM (x -> return . (x,) =<< p x) xs]


EDIT3: Another approach, because I'm not sure on precisely what you need access to.



filterM' p xs = [x | x <- filterM p xs]


Then, nest the comprehensions to obtain access to the "inner" element type eg. filtering and mapping,



filterMap f p xs = [[f x | x <- mlist] | mlist <- filterM p xs]





share|improve this answer



























  • I've added another edit, to emphasize the pragmatic motivation behind this. The point isn't to force it into a listcomp for the hell of it (fun and interesting though that may be!) In my edit you can see that the listcomp uses multiple input sets, and that there is a very clean translation to map+filter, which has a very clean translation to the monadic version, but it comes at the cost of having to uncurry the predicate and combiner. So the big-picture question is: is there a way of wirting it as a listcomp that is neater than the uncurry-filterM-mapM approach?

    – jacg
    Mar 29 at 12:05


















0
















import Control.Monad.Trans.Reader
import Control.Monad (filterM)


The question was motivated by the desire to take some functions of the form



f :: x -> y -> z -> a ; f = undefined
p :: x -> y -> z -> Bool ; p = undefined
u :: [x] -> [y] -> [z] -> [a]


and replace them with similar ones within some context (Reader in this example):



fR :: x -> y -> z -> Reader r a ; fR = undefined
pR :: x -> y -> z -> Reader r Bool ; pR = undefined
uR :: [x] -> [y] -> [z] -> Reader r [a]


At the core of the question, one of the original functions has a multi-input list comprehension that uses the other functions for combining and filtering purposes:



u xs ys zs = [ f x y z | x <- xs, y <- ys, z <- zs, p x y z ]


The question addresses the difficulties of implementing the equivalent, contextful, uR function; specifically the apparent loss of ability to use a list comprehension and its conveniences.



There is a fairly neat translation of u into an implementation that combines a list comprehension, filter and map. This is shown as u' below. u' has a direct translation to the contextful version, uR:



u' xs ys zs = map ucf $ filter ucp $ cartesian xs ys zs
uR xs ys zs = mapM ucfR =<< filterM ucpR =<< return (cartesian xs ys zs)


In the above, the list comprehension is packed up in cartesian



cartesian xs ys zs = [ (x,y,z) | x <- xs, y <- ys, z <- zs ]


and the solution requires the original functions (p, f, pR and fR) to be uncurried:



ucp = uncurry3 p ; ucpR = uncurry3 pR
ucf = uncurry3 f ; ucfR = uncurry3 fR

uncurry3 :: (a -> b -> c -> r) -> (a, b, c) -> r
uncurry3 f = (a,b,c) -> f a b c


Maybe this solution can be sugared with a monad comprehension, but I haven't the time to think about that right now.






share|improve this answer

























  • Sorry, the reason I wrote a few different versions was because I was experimenting myself and also because I wasn't exactly sure on your requirements. You have a few options, uR xs ys zs = sequence [ join [ fR x y z | True <- pR x y z ] | x <- xs, y <- ys, z <- zs ] is one of the clearer. You could remove the join by complicating the inner comprehension, and/or you can change the MonadFail constraint to Alternative by matching on the Bool directly ..[ r | r <- fR x y z, p <- pR x y z, p] (here both changes demonstrated). You may still feel the non-comprehension versions clearer though!

    – moonGoose
    Mar 29 at 21:04












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',
autoActivateHeartbeat: false,
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/4.0/"u003ecc by-sa 4.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%2f55401900%2flist-comprehension-guard-equivalent-of-filterm%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









1
















Personally, I can't figure out a way to do it with just a list comp, but this might get you closer? (I've listed some intermediate steps I went through so you can take it in a different direction if you need).



-# LANGUAGE MonadComprehensions #-

predicateM = return . (>3)
[[a | True <- predicateM a] | a <- [1,2,3,4,5]]
:: (Num b, Ord b, Control.Monad.Fail.MonadFail m) => [m b]
[[if b then Just a else Nothing | b <- predicateM a] | a <- [1,2,3,4,5]]
:: (Num a, Monad m, Ord a) => [m (Maybe a)]
[[bool Nothing (Just a) b | b <- predicateM a] | a <- [1,2,3,4,5]]
:: (Num a, Monad m, Ord a) => [m (Maybe a)]
catMaybes <$> sequence [[bool Nothing (Just a) b | b <- predicateM a] | a <- [1,2,3,4,5]]
:: (Monad f, Num a, Ord a) => f [a]

filterM' p xs = catMaybes <$> sequence [[bool Nothing (Just a) b | b <- p a] | a <- xs]


There may be something neater with a ListT?



EDIT: Another approach, although it spews some warnings about ListT giving unlawful instances..



unListT (ListT x) = x
filterM'' p xs = unListT [a | (a,True) <- ListT $ mapM (x -> return . (x,) =<< p x) xs]


EDIT2: Okay I got it down to a single comprehension!



filterM''' :: (Traversable m1, Monad m2, Monad m1, Alternative m1) => (b -> m2 Bool) -> m1 b -> m2 (m1 b)
filterM''' p xs = [[a | (a,b) <- mlist, b] | mlist <- mapM (x -> return . (x,) =<< p x) xs]


EDIT3: Another approach, because I'm not sure on precisely what you need access to.



filterM' p xs = [x | x <- filterM p xs]


Then, nest the comprehensions to obtain access to the "inner" element type eg. filtering and mapping,



filterMap f p xs = [[f x | x <- mlist] | mlist <- filterM p xs]





share|improve this answer



























  • I've added another edit, to emphasize the pragmatic motivation behind this. The point isn't to force it into a listcomp for the hell of it (fun and interesting though that may be!) In my edit you can see that the listcomp uses multiple input sets, and that there is a very clean translation to map+filter, which has a very clean translation to the monadic version, but it comes at the cost of having to uncurry the predicate and combiner. So the big-picture question is: is there a way of wirting it as a listcomp that is neater than the uncurry-filterM-mapM approach?

    – jacg
    Mar 29 at 12:05















1
















Personally, I can't figure out a way to do it with just a list comp, but this might get you closer? (I've listed some intermediate steps I went through so you can take it in a different direction if you need).



-# LANGUAGE MonadComprehensions #-

predicateM = return . (>3)
[[a | True <- predicateM a] | a <- [1,2,3,4,5]]
:: (Num b, Ord b, Control.Monad.Fail.MonadFail m) => [m b]
[[if b then Just a else Nothing | b <- predicateM a] | a <- [1,2,3,4,5]]
:: (Num a, Monad m, Ord a) => [m (Maybe a)]
[[bool Nothing (Just a) b | b <- predicateM a] | a <- [1,2,3,4,5]]
:: (Num a, Monad m, Ord a) => [m (Maybe a)]
catMaybes <$> sequence [[bool Nothing (Just a) b | b <- predicateM a] | a <- [1,2,3,4,5]]
:: (Monad f, Num a, Ord a) => f [a]

filterM' p xs = catMaybes <$> sequence [[bool Nothing (Just a) b | b <- p a] | a <- xs]


There may be something neater with a ListT?



EDIT: Another approach, although it spews some warnings about ListT giving unlawful instances..



unListT (ListT x) = x
filterM'' p xs = unListT [a | (a,True) <- ListT $ mapM (x -> return . (x,) =<< p x) xs]


EDIT2: Okay I got it down to a single comprehension!



filterM''' :: (Traversable m1, Monad m2, Monad m1, Alternative m1) => (b -> m2 Bool) -> m1 b -> m2 (m1 b)
filterM''' p xs = [[a | (a,b) <- mlist, b] | mlist <- mapM (x -> return . (x,) =<< p x) xs]


EDIT3: Another approach, because I'm not sure on precisely what you need access to.



filterM' p xs = [x | x <- filterM p xs]


Then, nest the comprehensions to obtain access to the "inner" element type eg. filtering and mapping,



filterMap f p xs = [[f x | x <- mlist] | mlist <- filterM p xs]





share|improve this answer



























  • I've added another edit, to emphasize the pragmatic motivation behind this. The point isn't to force it into a listcomp for the hell of it (fun and interesting though that may be!) In my edit you can see that the listcomp uses multiple input sets, and that there is a very clean translation to map+filter, which has a very clean translation to the monadic version, but it comes at the cost of having to uncurry the predicate and combiner. So the big-picture question is: is there a way of wirting it as a listcomp that is neater than the uncurry-filterM-mapM approach?

    – jacg
    Mar 29 at 12:05













1














1










1









Personally, I can't figure out a way to do it with just a list comp, but this might get you closer? (I've listed some intermediate steps I went through so you can take it in a different direction if you need).



-# LANGUAGE MonadComprehensions #-

predicateM = return . (>3)
[[a | True <- predicateM a] | a <- [1,2,3,4,5]]
:: (Num b, Ord b, Control.Monad.Fail.MonadFail m) => [m b]
[[if b then Just a else Nothing | b <- predicateM a] | a <- [1,2,3,4,5]]
:: (Num a, Monad m, Ord a) => [m (Maybe a)]
[[bool Nothing (Just a) b | b <- predicateM a] | a <- [1,2,3,4,5]]
:: (Num a, Monad m, Ord a) => [m (Maybe a)]
catMaybes <$> sequence [[bool Nothing (Just a) b | b <- predicateM a] | a <- [1,2,3,4,5]]
:: (Monad f, Num a, Ord a) => f [a]

filterM' p xs = catMaybes <$> sequence [[bool Nothing (Just a) b | b <- p a] | a <- xs]


There may be something neater with a ListT?



EDIT: Another approach, although it spews some warnings about ListT giving unlawful instances..



unListT (ListT x) = x
filterM'' p xs = unListT [a | (a,True) <- ListT $ mapM (x -> return . (x,) =<< p x) xs]


EDIT2: Okay I got it down to a single comprehension!



filterM''' :: (Traversable m1, Monad m2, Monad m1, Alternative m1) => (b -> m2 Bool) -> m1 b -> m2 (m1 b)
filterM''' p xs = [[a | (a,b) <- mlist, b] | mlist <- mapM (x -> return . (x,) =<< p x) xs]


EDIT3: Another approach, because I'm not sure on precisely what you need access to.



filterM' p xs = [x | x <- filterM p xs]


Then, nest the comprehensions to obtain access to the "inner" element type eg. filtering and mapping,



filterMap f p xs = [[f x | x <- mlist] | mlist <- filterM p xs]





share|improve this answer















Personally, I can't figure out a way to do it with just a list comp, but this might get you closer? (I've listed some intermediate steps I went through so you can take it in a different direction if you need).



-# LANGUAGE MonadComprehensions #-

predicateM = return . (>3)
[[a | True <- predicateM a] | a <- [1,2,3,4,5]]
:: (Num b, Ord b, Control.Monad.Fail.MonadFail m) => [m b]
[[if b then Just a else Nothing | b <- predicateM a] | a <- [1,2,3,4,5]]
:: (Num a, Monad m, Ord a) => [m (Maybe a)]
[[bool Nothing (Just a) b | b <- predicateM a] | a <- [1,2,3,4,5]]
:: (Num a, Monad m, Ord a) => [m (Maybe a)]
catMaybes <$> sequence [[bool Nothing (Just a) b | b <- predicateM a] | a <- [1,2,3,4,5]]
:: (Monad f, Num a, Ord a) => f [a]

filterM' p xs = catMaybes <$> sequence [[bool Nothing (Just a) b | b <- p a] | a <- xs]


There may be something neater with a ListT?



EDIT: Another approach, although it spews some warnings about ListT giving unlawful instances..



unListT (ListT x) = x
filterM'' p xs = unListT [a | (a,True) <- ListT $ mapM (x -> return . (x,) =<< p x) xs]


EDIT2: Okay I got it down to a single comprehension!



filterM''' :: (Traversable m1, Monad m2, Monad m1, Alternative m1) => (b -> m2 Bool) -> m1 b -> m2 (m1 b)
filterM''' p xs = [[a | (a,b) <- mlist, b] | mlist <- mapM (x -> return . (x,) =<< p x) xs]


EDIT3: Another approach, because I'm not sure on precisely what you need access to.



filterM' p xs = [x | x <- filterM p xs]


Then, nest the comprehensions to obtain access to the "inner" element type eg. filtering and mapping,



filterMap f p xs = [[f x | x <- mlist] | mlist <- filterM p xs]






share|improve this answer














share|improve this answer



share|improve this answer








edited Mar 29 at 0:16

























answered Mar 28 at 21:12









moonGoosemoonGoose

1,2532 silver badges12 bronze badges




1,2532 silver badges12 bronze badges















  • I've added another edit, to emphasize the pragmatic motivation behind this. The point isn't to force it into a listcomp for the hell of it (fun and interesting though that may be!) In my edit you can see that the listcomp uses multiple input sets, and that there is a very clean translation to map+filter, which has a very clean translation to the monadic version, but it comes at the cost of having to uncurry the predicate and combiner. So the big-picture question is: is there a way of wirting it as a listcomp that is neater than the uncurry-filterM-mapM approach?

    – jacg
    Mar 29 at 12:05

















  • I've added another edit, to emphasize the pragmatic motivation behind this. The point isn't to force it into a listcomp for the hell of it (fun and interesting though that may be!) In my edit you can see that the listcomp uses multiple input sets, and that there is a very clean translation to map+filter, which has a very clean translation to the monadic version, but it comes at the cost of having to uncurry the predicate and combiner. So the big-picture question is: is there a way of wirting it as a listcomp that is neater than the uncurry-filterM-mapM approach?

    – jacg
    Mar 29 at 12:05
















I've added another edit, to emphasize the pragmatic motivation behind this. The point isn't to force it into a listcomp for the hell of it (fun and interesting though that may be!) In my edit you can see that the listcomp uses multiple input sets, and that there is a very clean translation to map+filter, which has a very clean translation to the monadic version, but it comes at the cost of having to uncurry the predicate and combiner. So the big-picture question is: is there a way of wirting it as a listcomp that is neater than the uncurry-filterM-mapM approach?

– jacg
Mar 29 at 12:05





I've added another edit, to emphasize the pragmatic motivation behind this. The point isn't to force it into a listcomp for the hell of it (fun and interesting though that may be!) In my edit you can see that the listcomp uses multiple input sets, and that there is a very clean translation to map+filter, which has a very clean translation to the monadic version, but it comes at the cost of having to uncurry the predicate and combiner. So the big-picture question is: is there a way of wirting it as a listcomp that is neater than the uncurry-filterM-mapM approach?

– jacg
Mar 29 at 12:05













0
















import Control.Monad.Trans.Reader
import Control.Monad (filterM)


The question was motivated by the desire to take some functions of the form



f :: x -> y -> z -> a ; f = undefined
p :: x -> y -> z -> Bool ; p = undefined
u :: [x] -> [y] -> [z] -> [a]


and replace them with similar ones within some context (Reader in this example):



fR :: x -> y -> z -> Reader r a ; fR = undefined
pR :: x -> y -> z -> Reader r Bool ; pR = undefined
uR :: [x] -> [y] -> [z] -> Reader r [a]


At the core of the question, one of the original functions has a multi-input list comprehension that uses the other functions for combining and filtering purposes:



u xs ys zs = [ f x y z | x <- xs, y <- ys, z <- zs, p x y z ]


The question addresses the difficulties of implementing the equivalent, contextful, uR function; specifically the apparent loss of ability to use a list comprehension and its conveniences.



There is a fairly neat translation of u into an implementation that combines a list comprehension, filter and map. This is shown as u' below. u' has a direct translation to the contextful version, uR:



u' xs ys zs = map ucf $ filter ucp $ cartesian xs ys zs
uR xs ys zs = mapM ucfR =<< filterM ucpR =<< return (cartesian xs ys zs)


In the above, the list comprehension is packed up in cartesian



cartesian xs ys zs = [ (x,y,z) | x <- xs, y <- ys, z <- zs ]


and the solution requires the original functions (p, f, pR and fR) to be uncurried:



ucp = uncurry3 p ; ucpR = uncurry3 pR
ucf = uncurry3 f ; ucfR = uncurry3 fR

uncurry3 :: (a -> b -> c -> r) -> (a, b, c) -> r
uncurry3 f = (a,b,c) -> f a b c


Maybe this solution can be sugared with a monad comprehension, but I haven't the time to think about that right now.






share|improve this answer

























  • Sorry, the reason I wrote a few different versions was because I was experimenting myself and also because I wasn't exactly sure on your requirements. You have a few options, uR xs ys zs = sequence [ join [ fR x y z | True <- pR x y z ] | x <- xs, y <- ys, z <- zs ] is one of the clearer. You could remove the join by complicating the inner comprehension, and/or you can change the MonadFail constraint to Alternative by matching on the Bool directly ..[ r | r <- fR x y z, p <- pR x y z, p] (here both changes demonstrated). You may still feel the non-comprehension versions clearer though!

    – moonGoose
    Mar 29 at 21:04















0
















import Control.Monad.Trans.Reader
import Control.Monad (filterM)


The question was motivated by the desire to take some functions of the form



f :: x -> y -> z -> a ; f = undefined
p :: x -> y -> z -> Bool ; p = undefined
u :: [x] -> [y] -> [z] -> [a]


and replace them with similar ones within some context (Reader in this example):



fR :: x -> y -> z -> Reader r a ; fR = undefined
pR :: x -> y -> z -> Reader r Bool ; pR = undefined
uR :: [x] -> [y] -> [z] -> Reader r [a]


At the core of the question, one of the original functions has a multi-input list comprehension that uses the other functions for combining and filtering purposes:



u xs ys zs = [ f x y z | x <- xs, y <- ys, z <- zs, p x y z ]


The question addresses the difficulties of implementing the equivalent, contextful, uR function; specifically the apparent loss of ability to use a list comprehension and its conveniences.



There is a fairly neat translation of u into an implementation that combines a list comprehension, filter and map. This is shown as u' below. u' has a direct translation to the contextful version, uR:



u' xs ys zs = map ucf $ filter ucp $ cartesian xs ys zs
uR xs ys zs = mapM ucfR =<< filterM ucpR =<< return (cartesian xs ys zs)


In the above, the list comprehension is packed up in cartesian



cartesian xs ys zs = [ (x,y,z) | x <- xs, y <- ys, z <- zs ]


and the solution requires the original functions (p, f, pR and fR) to be uncurried:



ucp = uncurry3 p ; ucpR = uncurry3 pR
ucf = uncurry3 f ; ucfR = uncurry3 fR

uncurry3 :: (a -> b -> c -> r) -> (a, b, c) -> r
uncurry3 f = (a,b,c) -> f a b c


Maybe this solution can be sugared with a monad comprehension, but I haven't the time to think about that right now.






share|improve this answer

























  • Sorry, the reason I wrote a few different versions was because I was experimenting myself and also because I wasn't exactly sure on your requirements. You have a few options, uR xs ys zs = sequence [ join [ fR x y z | True <- pR x y z ] | x <- xs, y <- ys, z <- zs ] is one of the clearer. You could remove the join by complicating the inner comprehension, and/or you can change the MonadFail constraint to Alternative by matching on the Bool directly ..[ r | r <- fR x y z, p <- pR x y z, p] (here both changes demonstrated). You may still feel the non-comprehension versions clearer though!

    – moonGoose
    Mar 29 at 21:04













0














0










0









import Control.Monad.Trans.Reader
import Control.Monad (filterM)


The question was motivated by the desire to take some functions of the form



f :: x -> y -> z -> a ; f = undefined
p :: x -> y -> z -> Bool ; p = undefined
u :: [x] -> [y] -> [z] -> [a]


and replace them with similar ones within some context (Reader in this example):



fR :: x -> y -> z -> Reader r a ; fR = undefined
pR :: x -> y -> z -> Reader r Bool ; pR = undefined
uR :: [x] -> [y] -> [z] -> Reader r [a]


At the core of the question, one of the original functions has a multi-input list comprehension that uses the other functions for combining and filtering purposes:



u xs ys zs = [ f x y z | x <- xs, y <- ys, z <- zs, p x y z ]


The question addresses the difficulties of implementing the equivalent, contextful, uR function; specifically the apparent loss of ability to use a list comprehension and its conveniences.



There is a fairly neat translation of u into an implementation that combines a list comprehension, filter and map. This is shown as u' below. u' has a direct translation to the contextful version, uR:



u' xs ys zs = map ucf $ filter ucp $ cartesian xs ys zs
uR xs ys zs = mapM ucfR =<< filterM ucpR =<< return (cartesian xs ys zs)


In the above, the list comprehension is packed up in cartesian



cartesian xs ys zs = [ (x,y,z) | x <- xs, y <- ys, z <- zs ]


and the solution requires the original functions (p, f, pR and fR) to be uncurried:



ucp = uncurry3 p ; ucpR = uncurry3 pR
ucf = uncurry3 f ; ucfR = uncurry3 fR

uncurry3 :: (a -> b -> c -> r) -> (a, b, c) -> r
uncurry3 f = (a,b,c) -> f a b c


Maybe this solution can be sugared with a monad comprehension, but I haven't the time to think about that right now.






share|improve this answer













import Control.Monad.Trans.Reader
import Control.Monad (filterM)


The question was motivated by the desire to take some functions of the form



f :: x -> y -> z -> a ; f = undefined
p :: x -> y -> z -> Bool ; p = undefined
u :: [x] -> [y] -> [z] -> [a]


and replace them with similar ones within some context (Reader in this example):



fR :: x -> y -> z -> Reader r a ; fR = undefined
pR :: x -> y -> z -> Reader r Bool ; pR = undefined
uR :: [x] -> [y] -> [z] -> Reader r [a]


At the core of the question, one of the original functions has a multi-input list comprehension that uses the other functions for combining and filtering purposes:



u xs ys zs = [ f x y z | x <- xs, y <- ys, z <- zs, p x y z ]


The question addresses the difficulties of implementing the equivalent, contextful, uR function; specifically the apparent loss of ability to use a list comprehension and its conveniences.



There is a fairly neat translation of u into an implementation that combines a list comprehension, filter and map. This is shown as u' below. u' has a direct translation to the contextful version, uR:



u' xs ys zs = map ucf $ filter ucp $ cartesian xs ys zs
uR xs ys zs = mapM ucfR =<< filterM ucpR =<< return (cartesian xs ys zs)


In the above, the list comprehension is packed up in cartesian



cartesian xs ys zs = [ (x,y,z) | x <- xs, y <- ys, z <- zs ]


and the solution requires the original functions (p, f, pR and fR) to be uncurried:



ucp = uncurry3 p ; ucpR = uncurry3 pR
ucf = uncurry3 f ; ucfR = uncurry3 fR

uncurry3 :: (a -> b -> c -> r) -> (a, b, c) -> r
uncurry3 f = (a,b,c) -> f a b c


Maybe this solution can be sugared with a monad comprehension, but I haven't the time to think about that right now.







share|improve this answer












share|improve this answer



share|improve this answer










answered Mar 29 at 12:38









jacgjacg

1,2086 silver badges19 bronze badges




1,2086 silver badges19 bronze badges















  • Sorry, the reason I wrote a few different versions was because I was experimenting myself and also because I wasn't exactly sure on your requirements. You have a few options, uR xs ys zs = sequence [ join [ fR x y z | True <- pR x y z ] | x <- xs, y <- ys, z <- zs ] is one of the clearer. You could remove the join by complicating the inner comprehension, and/or you can change the MonadFail constraint to Alternative by matching on the Bool directly ..[ r | r <- fR x y z, p <- pR x y z, p] (here both changes demonstrated). You may still feel the non-comprehension versions clearer though!

    – moonGoose
    Mar 29 at 21:04

















  • Sorry, the reason I wrote a few different versions was because I was experimenting myself and also because I wasn't exactly sure on your requirements. You have a few options, uR xs ys zs = sequence [ join [ fR x y z | True <- pR x y z ] | x <- xs, y <- ys, z <- zs ] is one of the clearer. You could remove the join by complicating the inner comprehension, and/or you can change the MonadFail constraint to Alternative by matching on the Bool directly ..[ r | r <- fR x y z, p <- pR x y z, p] (here both changes demonstrated). You may still feel the non-comprehension versions clearer though!

    – moonGoose
    Mar 29 at 21:04
















Sorry, the reason I wrote a few different versions was because I was experimenting myself and also because I wasn't exactly sure on your requirements. You have a few options, uR xs ys zs = sequence [ join [ fR x y z | True <- pR x y z ] | x <- xs, y <- ys, z <- zs ] is one of the clearer. You could remove the join by complicating the inner comprehension, and/or you can change the MonadFail constraint to Alternative by matching on the Bool directly ..[ r | r <- fR x y z, p <- pR x y z, p] (here both changes demonstrated). You may still feel the non-comprehension versions clearer though!

– moonGoose
Mar 29 at 21:04





Sorry, the reason I wrote a few different versions was because I was experimenting myself and also because I wasn't exactly sure on your requirements. You have a few options, uR xs ys zs = sequence [ join [ fR x y z | True <- pR x y z ] | x <- xs, y <- ys, z <- zs ] is one of the clearer. You could remove the join by complicating the inner comprehension, and/or you can change the MonadFail constraint to Alternative by matching on the Bool directly ..[ r | r <- fR x y z, p <- pR x y z, p] (here both changes demonstrated). You may still feel the non-comprehension versions clearer though!

– moonGoose
Mar 29 at 21:04


















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.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55401900%2flist-comprehension-guard-equivalent-of-filterm%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

Kamusi Yaliyomo Aina za kamusi | Muundo wa kamusi | Faida za kamusi | Dhima ya picha katika kamusi | Marejeo | Tazama pia | Viungo vya nje | UrambazajiKuhusu kamusiGo-SwahiliWiki-KamusiKamusi ya Kiswahili na Kiingerezakuihariri na kuongeza habari

Swift 4 - func physicsWorld not invoked on collision? The Next CEO of Stack OverflowHow to call Objective-C code from Swift#ifdef replacement in the Swift language@selector() in Swift?#pragma mark in Swift?Swift for loop: for index, element in array?dispatch_after - GCD in Swift?Swift Beta performance: sorting arraysSplit a String into an array in Swift?The use of Swift 3 @objc inference in Swift 4 mode is deprecated?How to optimize UITableViewCell, because my UITableView lags

Access current req object everywhere in Node.js ExpressWhy are global variables considered bad practice? (node.js)Using req & res across functionsHow do I get the path to the current script with Node.js?What is Node.js' Connect, Express and “middleware”?Node.js w/ express error handling in callbackHow to access the GET parameters after “?” in Express?Modify Node.js req object parametersAccess “app” variable inside of ExpressJS/ConnectJS middleware?Node.js Express app - request objectAngular Http Module considered middleware?Session variables in ExpressJSAdd properties to the req object in expressjs with Typescript