Can my implementation of filter be improved?
up vote
6
down vote
favorite
An exercise in Haskell from First Principles says to implement filter
using foldr
and this is what I came up with but it feels and looks clunky. Is there a more natural way to implement it with a foldr
?
import Data.Bool
myFilter :: (a -> Bool) -> [a] -> [a]
myFilter f = foldr (x -> bool (++ ) ((:) x) (f x))
haskell fold
add a comment |
up vote
6
down vote
favorite
An exercise in Haskell from First Principles says to implement filter
using foldr
and this is what I came up with but it feels and looks clunky. Is there a more natural way to implement it with a foldr
?
import Data.Bool
myFilter :: (a -> Bool) -> [a] -> [a]
myFilter f = foldr (x -> bool (++ ) ((:) x) (f x))
haskell fold
9
(++)
is justid
.
– Willem Van Onsem
Nov 7 at 20:14
3
I'm not sure anyone would find((:) x)
less clunky than(x :)
.
– chepner
Nov 7 at 20:20
@chepner I changed that one a few seconds ago lol.
– Brady Dean
Nov 7 at 20:21
1
@chepner what do you mean? (⊢ never (is clunky (notation 'prefix)))
– leftaroundabout
Nov 7 at 20:24
add a comment |
up vote
6
down vote
favorite
up vote
6
down vote
favorite
An exercise in Haskell from First Principles says to implement filter
using foldr
and this is what I came up with but it feels and looks clunky. Is there a more natural way to implement it with a foldr
?
import Data.Bool
myFilter :: (a -> Bool) -> [a] -> [a]
myFilter f = foldr (x -> bool (++ ) ((:) x) (f x))
haskell fold
An exercise in Haskell from First Principles says to implement filter
using foldr
and this is what I came up with but it feels and looks clunky. Is there a more natural way to implement it with a foldr
?
import Data.Bool
myFilter :: (a -> Bool) -> [a] -> [a]
myFilter f = foldr (x -> bool (++ ) ((:) x) (f x))
haskell fold
haskell fold
asked Nov 7 at 20:13
Brady Dean
6911624
6911624
9
(++)
is justid
.
– Willem Van Onsem
Nov 7 at 20:14
3
I'm not sure anyone would find((:) x)
less clunky than(x :)
.
– chepner
Nov 7 at 20:20
@chepner I changed that one a few seconds ago lol.
– Brady Dean
Nov 7 at 20:21
1
@chepner what do you mean? (⊢ never (is clunky (notation 'prefix)))
– leftaroundabout
Nov 7 at 20:24
add a comment |
9
(++)
is justid
.
– Willem Van Onsem
Nov 7 at 20:14
3
I'm not sure anyone would find((:) x)
less clunky than(x :)
.
– chepner
Nov 7 at 20:20
@chepner I changed that one a few seconds ago lol.
– Brady Dean
Nov 7 at 20:21
1
@chepner what do you mean? (⊢ never (is clunky (notation 'prefix)))
– leftaroundabout
Nov 7 at 20:24
9
9
(++)
is just id
.– Willem Van Onsem
Nov 7 at 20:14
(++)
is just id
.– Willem Van Onsem
Nov 7 at 20:14
3
3
I'm not sure anyone would find
((:) x)
less clunky than (x :)
.– chepner
Nov 7 at 20:20
I'm not sure anyone would find
((:) x)
less clunky than (x :)
.– chepner
Nov 7 at 20:20
@chepner I changed that one a few seconds ago lol.
– Brady Dean
Nov 7 at 20:21
@chepner I changed that one a few seconds ago lol.
– Brady Dean
Nov 7 at 20:21
1
1
@chepner what do you mean? (⊢ never (is clunky (notation 'prefix)))
– leftaroundabout
Nov 7 at 20:24
@chepner what do you mean? (⊢ never (is clunky (notation 'prefix)))
– leftaroundabout
Nov 7 at 20:24
add a comment |
4 Answers
4
active
oldest
votes
up vote
5
down vote
accepted
I would only use bool
if it let me get rid of the lambda expression simply, by composing a call to bool
with the predicate p
: bool iffalse iftrue . p
. However, p
isn't the only function that needs to be called on a list element; (:)
does as well. You could use the Applicative
instance for functions, to write
myfilter p = foldr (bool id . (:) <*> p) -- yuck
but in this case I would just use a plain if
expression, inside the lambda expression:
myfilter p = foldr (x -> if p x then (x:) else id) -- much clearer!
Note that when specialized to functions, the Applicative
's (<*>)
operator is defined as f <*> g = x -> f x (g x)
. I leave it as an exercise to use that definition to transform bool id . (:) <*> p
into
x -> bool id (x:) (p x)
.
2
That applicative code is indeed quite obfuscated. I also greatly prefer the plain code below.
– chi
Nov 7 at 21:32
add a comment |
up vote
2
down vote
You can use the Applicative
instance of (->) a
to make the lambda cleaner. But, if you want to use foldr
, I don't think there's any substantial change you can effect:
myFilter f = foldr (bool id <$> (:) <*> f)
bool id <$> (:) <*> f
means x -> bool id ((:) x) (f x)
. bool id
has type ([a] -> [a]) -> Bool -> ([a] -> [a])
. (:)
has type a -> [a] -> [a]
, and f
has type a -> Bool
. When (<$>)
and (<*>)
are used in this way, you can think of it as pretending that (:)
and f
don't have an a
argument, making them [a] -> [a]
and Bool
, respectively, applying them to bool id
to get a [a] -> [a]
, and then ending the lie by reintroducing the a
argument, making a a -> [a] -> [a]
. The operators are in charge of threading that a
around, so you don't need a lambda abstraction.
I'm not familiar withApplicative
yet but thanks for the answer.
– Brady Dean
Nov 7 at 20:52
add a comment |
up vote
1
down vote
Rather than merely searching for a more elegant implementation, it would might help you more to learn an elegant process of searching for an implementation. This should make it simpler to find elegant solutions.
For any function h
on lists we have that,
h = foldr f e
if and only if
h = e
h (x:xs) = f x (h xs)
In this case your h
is filter p
for some boolean function p
that selects which elements to keep. Implementing filter p
as a "simple" recursive function is not too hard.
filter p =
filter p (x:xs) = if p x then x : (filter p xs) else (filter p xs)
The 1st line implies e =
. The 2nd line needs to be written in the form f x (filter p xs)
to match the equation of h
above, in order for us to deduce which f
to plug in the foldr
. To do that we just abstract over those two expressions.
filter p =
filter p (x:xs) = (x ys -> if p x then x : ys else ys) x (filter p xs)
So we have found that,
e =
f x ys = if p x then x: ys else ys
It therefore follows,
filter p = foldr (y ys -> if p y then y : ys else ys)
To learn more about this method of working with foldr
I recommend reading
"A tutorial on the universality and expressiveness of fold" by Graham Hutton.
Some added notes:
In case this seems overly complicated, note that while the principles above can be used in this "semi rigorous" fashion via algebraic manipulation, they can and should also be used to guide your intuition and aid you in informal development.
The equation for h (x:xs) = f x (h xs)
sheds some clarity on how to find f
. In the case where h
is the filtering function you want an f
which combines the element x
with a tail that has already been filtered. If you really understand this it should be easy to arrive at,
f x ys = if p x then x : ys else ys
1
did you perhaps meanf y ys = if p y then y : ys else ys
in the last line? BTW it can also be writtenf y ys = [y | p y] ++ ys
.
– Will Ness
Nov 8 at 15:48
ops missed that, I thought x would be clearer in that context but forgot to change the p y to p x
– Jorge Adriano
Nov 8 at 17:19
I also sensed some Richard Bird in there, esp. at the start, from his "theory of lists"... :) is it so?
– Will Ness
Nov 8 at 17:24
Possibly, since my very first book on Haskell was his classic "Introduction to Functional Programming using Haskell", but never read that particular paper to be honest.
– Jorge Adriano
Nov 8 at 17:52
add a comment |
up vote
0
down vote
Yes, there is:
myFilter :: (a -> Bool) -> [a] -> [a]
myFilter f = foldMap (x -> [x | f x])
> myFilter even [1..10]
[2,4,6,8,10]
See, I switched it on you, with foldMap
.
Well, with foldr
it is foldr (x -> ([x | f x] ++))
.
add a comment |
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
5
down vote
accepted
I would only use bool
if it let me get rid of the lambda expression simply, by composing a call to bool
with the predicate p
: bool iffalse iftrue . p
. However, p
isn't the only function that needs to be called on a list element; (:)
does as well. You could use the Applicative
instance for functions, to write
myfilter p = foldr (bool id . (:) <*> p) -- yuck
but in this case I would just use a plain if
expression, inside the lambda expression:
myfilter p = foldr (x -> if p x then (x:) else id) -- much clearer!
Note that when specialized to functions, the Applicative
's (<*>)
operator is defined as f <*> g = x -> f x (g x)
. I leave it as an exercise to use that definition to transform bool id . (:) <*> p
into
x -> bool id (x:) (p x)
.
2
That applicative code is indeed quite obfuscated. I also greatly prefer the plain code below.
– chi
Nov 7 at 21:32
add a comment |
up vote
5
down vote
accepted
I would only use bool
if it let me get rid of the lambda expression simply, by composing a call to bool
with the predicate p
: bool iffalse iftrue . p
. However, p
isn't the only function that needs to be called on a list element; (:)
does as well. You could use the Applicative
instance for functions, to write
myfilter p = foldr (bool id . (:) <*> p) -- yuck
but in this case I would just use a plain if
expression, inside the lambda expression:
myfilter p = foldr (x -> if p x then (x:) else id) -- much clearer!
Note that when specialized to functions, the Applicative
's (<*>)
operator is defined as f <*> g = x -> f x (g x)
. I leave it as an exercise to use that definition to transform bool id . (:) <*> p
into
x -> bool id (x:) (p x)
.
2
That applicative code is indeed quite obfuscated. I also greatly prefer the plain code below.
– chi
Nov 7 at 21:32
add a comment |
up vote
5
down vote
accepted
up vote
5
down vote
accepted
I would only use bool
if it let me get rid of the lambda expression simply, by composing a call to bool
with the predicate p
: bool iffalse iftrue . p
. However, p
isn't the only function that needs to be called on a list element; (:)
does as well. You could use the Applicative
instance for functions, to write
myfilter p = foldr (bool id . (:) <*> p) -- yuck
but in this case I would just use a plain if
expression, inside the lambda expression:
myfilter p = foldr (x -> if p x then (x:) else id) -- much clearer!
Note that when specialized to functions, the Applicative
's (<*>)
operator is defined as f <*> g = x -> f x (g x)
. I leave it as an exercise to use that definition to transform bool id . (:) <*> p
into
x -> bool id (x:) (p x)
.
I would only use bool
if it let me get rid of the lambda expression simply, by composing a call to bool
with the predicate p
: bool iffalse iftrue . p
. However, p
isn't the only function that needs to be called on a list element; (:)
does as well. You could use the Applicative
instance for functions, to write
myfilter p = foldr (bool id . (:) <*> p) -- yuck
but in this case I would just use a plain if
expression, inside the lambda expression:
myfilter p = foldr (x -> if p x then (x:) else id) -- much clearer!
Note that when specialized to functions, the Applicative
's (<*>)
operator is defined as f <*> g = x -> f x (g x)
. I leave it as an exercise to use that definition to transform bool id . (:) <*> p
into
x -> bool id (x:) (p x)
.
edited Nov 9 at 17:00
Will Ness
42k467118
42k467118
answered Nov 7 at 20:47
chepner
238k29223318
238k29223318
2
That applicative code is indeed quite obfuscated. I also greatly prefer the plain code below.
– chi
Nov 7 at 21:32
add a comment |
2
That applicative code is indeed quite obfuscated. I also greatly prefer the plain code below.
– chi
Nov 7 at 21:32
2
2
That applicative code is indeed quite obfuscated. I also greatly prefer the plain code below.
– chi
Nov 7 at 21:32
That applicative code is indeed quite obfuscated. I also greatly prefer the plain code below.
– chi
Nov 7 at 21:32
add a comment |
up vote
2
down vote
You can use the Applicative
instance of (->) a
to make the lambda cleaner. But, if you want to use foldr
, I don't think there's any substantial change you can effect:
myFilter f = foldr (bool id <$> (:) <*> f)
bool id <$> (:) <*> f
means x -> bool id ((:) x) (f x)
. bool id
has type ([a] -> [a]) -> Bool -> ([a] -> [a])
. (:)
has type a -> [a] -> [a]
, and f
has type a -> Bool
. When (<$>)
and (<*>)
are used in this way, you can think of it as pretending that (:)
and f
don't have an a
argument, making them [a] -> [a]
and Bool
, respectively, applying them to bool id
to get a [a] -> [a]
, and then ending the lie by reintroducing the a
argument, making a a -> [a] -> [a]
. The operators are in charge of threading that a
around, so you don't need a lambda abstraction.
I'm not familiar withApplicative
yet but thanks for the answer.
– Brady Dean
Nov 7 at 20:52
add a comment |
up vote
2
down vote
You can use the Applicative
instance of (->) a
to make the lambda cleaner. But, if you want to use foldr
, I don't think there's any substantial change you can effect:
myFilter f = foldr (bool id <$> (:) <*> f)
bool id <$> (:) <*> f
means x -> bool id ((:) x) (f x)
. bool id
has type ([a] -> [a]) -> Bool -> ([a] -> [a])
. (:)
has type a -> [a] -> [a]
, and f
has type a -> Bool
. When (<$>)
and (<*>)
are used in this way, you can think of it as pretending that (:)
and f
don't have an a
argument, making them [a] -> [a]
and Bool
, respectively, applying them to bool id
to get a [a] -> [a]
, and then ending the lie by reintroducing the a
argument, making a a -> [a] -> [a]
. The operators are in charge of threading that a
around, so you don't need a lambda abstraction.
I'm not familiar withApplicative
yet but thanks for the answer.
– Brady Dean
Nov 7 at 20:52
add a comment |
up vote
2
down vote
up vote
2
down vote
You can use the Applicative
instance of (->) a
to make the lambda cleaner. But, if you want to use foldr
, I don't think there's any substantial change you can effect:
myFilter f = foldr (bool id <$> (:) <*> f)
bool id <$> (:) <*> f
means x -> bool id ((:) x) (f x)
. bool id
has type ([a] -> [a]) -> Bool -> ([a] -> [a])
. (:)
has type a -> [a] -> [a]
, and f
has type a -> Bool
. When (<$>)
and (<*>)
are used in this way, you can think of it as pretending that (:)
and f
don't have an a
argument, making them [a] -> [a]
and Bool
, respectively, applying them to bool id
to get a [a] -> [a]
, and then ending the lie by reintroducing the a
argument, making a a -> [a] -> [a]
. The operators are in charge of threading that a
around, so you don't need a lambda abstraction.
You can use the Applicative
instance of (->) a
to make the lambda cleaner. But, if you want to use foldr
, I don't think there's any substantial change you can effect:
myFilter f = foldr (bool id <$> (:) <*> f)
bool id <$> (:) <*> f
means x -> bool id ((:) x) (f x)
. bool id
has type ([a] -> [a]) -> Bool -> ([a] -> [a])
. (:)
has type a -> [a] -> [a]
, and f
has type a -> Bool
. When (<$>)
and (<*>)
are used in this way, you can think of it as pretending that (:)
and f
don't have an a
argument, making them [a] -> [a]
and Bool
, respectively, applying them to bool id
to get a [a] -> [a]
, and then ending the lie by reintroducing the a
argument, making a a -> [a] -> [a]
. The operators are in charge of threading that a
around, so you don't need a lambda abstraction.
answered Nov 7 at 20:45
HTNW
9,0941732
9,0941732
I'm not familiar withApplicative
yet but thanks for the answer.
– Brady Dean
Nov 7 at 20:52
add a comment |
I'm not familiar withApplicative
yet but thanks for the answer.
– Brady Dean
Nov 7 at 20:52
I'm not familiar with
Applicative
yet but thanks for the answer.– Brady Dean
Nov 7 at 20:52
I'm not familiar with
Applicative
yet but thanks for the answer.– Brady Dean
Nov 7 at 20:52
add a comment |
up vote
1
down vote
Rather than merely searching for a more elegant implementation, it would might help you more to learn an elegant process of searching for an implementation. This should make it simpler to find elegant solutions.
For any function h
on lists we have that,
h = foldr f e
if and only if
h = e
h (x:xs) = f x (h xs)
In this case your h
is filter p
for some boolean function p
that selects which elements to keep. Implementing filter p
as a "simple" recursive function is not too hard.
filter p =
filter p (x:xs) = if p x then x : (filter p xs) else (filter p xs)
The 1st line implies e =
. The 2nd line needs to be written in the form f x (filter p xs)
to match the equation of h
above, in order for us to deduce which f
to plug in the foldr
. To do that we just abstract over those two expressions.
filter p =
filter p (x:xs) = (x ys -> if p x then x : ys else ys) x (filter p xs)
So we have found that,
e =
f x ys = if p x then x: ys else ys
It therefore follows,
filter p = foldr (y ys -> if p y then y : ys else ys)
To learn more about this method of working with foldr
I recommend reading
"A tutorial on the universality and expressiveness of fold" by Graham Hutton.
Some added notes:
In case this seems overly complicated, note that while the principles above can be used in this "semi rigorous" fashion via algebraic manipulation, they can and should also be used to guide your intuition and aid you in informal development.
The equation for h (x:xs) = f x (h xs)
sheds some clarity on how to find f
. In the case where h
is the filtering function you want an f
which combines the element x
with a tail that has already been filtered. If you really understand this it should be easy to arrive at,
f x ys = if p x then x : ys else ys
1
did you perhaps meanf y ys = if p y then y : ys else ys
in the last line? BTW it can also be writtenf y ys = [y | p y] ++ ys
.
– Will Ness
Nov 8 at 15:48
ops missed that, I thought x would be clearer in that context but forgot to change the p y to p x
– Jorge Adriano
Nov 8 at 17:19
I also sensed some Richard Bird in there, esp. at the start, from his "theory of lists"... :) is it so?
– Will Ness
Nov 8 at 17:24
Possibly, since my very first book on Haskell was his classic "Introduction to Functional Programming using Haskell", but never read that particular paper to be honest.
– Jorge Adriano
Nov 8 at 17:52
add a comment |
up vote
1
down vote
Rather than merely searching for a more elegant implementation, it would might help you more to learn an elegant process of searching for an implementation. This should make it simpler to find elegant solutions.
For any function h
on lists we have that,
h = foldr f e
if and only if
h = e
h (x:xs) = f x (h xs)
In this case your h
is filter p
for some boolean function p
that selects which elements to keep. Implementing filter p
as a "simple" recursive function is not too hard.
filter p =
filter p (x:xs) = if p x then x : (filter p xs) else (filter p xs)
The 1st line implies e =
. The 2nd line needs to be written in the form f x (filter p xs)
to match the equation of h
above, in order for us to deduce which f
to plug in the foldr
. To do that we just abstract over those two expressions.
filter p =
filter p (x:xs) = (x ys -> if p x then x : ys else ys) x (filter p xs)
So we have found that,
e =
f x ys = if p x then x: ys else ys
It therefore follows,
filter p = foldr (y ys -> if p y then y : ys else ys)
To learn more about this method of working with foldr
I recommend reading
"A tutorial on the universality and expressiveness of fold" by Graham Hutton.
Some added notes:
In case this seems overly complicated, note that while the principles above can be used in this "semi rigorous" fashion via algebraic manipulation, they can and should also be used to guide your intuition and aid you in informal development.
The equation for h (x:xs) = f x (h xs)
sheds some clarity on how to find f
. In the case where h
is the filtering function you want an f
which combines the element x
with a tail that has already been filtered. If you really understand this it should be easy to arrive at,
f x ys = if p x then x : ys else ys
1
did you perhaps meanf y ys = if p y then y : ys else ys
in the last line? BTW it can also be writtenf y ys = [y | p y] ++ ys
.
– Will Ness
Nov 8 at 15:48
ops missed that, I thought x would be clearer in that context but forgot to change the p y to p x
– Jorge Adriano
Nov 8 at 17:19
I also sensed some Richard Bird in there, esp. at the start, from his "theory of lists"... :) is it so?
– Will Ness
Nov 8 at 17:24
Possibly, since my very first book on Haskell was his classic "Introduction to Functional Programming using Haskell", but never read that particular paper to be honest.
– Jorge Adriano
Nov 8 at 17:52
add a comment |
up vote
1
down vote
up vote
1
down vote
Rather than merely searching for a more elegant implementation, it would might help you more to learn an elegant process of searching for an implementation. This should make it simpler to find elegant solutions.
For any function h
on lists we have that,
h = foldr f e
if and only if
h = e
h (x:xs) = f x (h xs)
In this case your h
is filter p
for some boolean function p
that selects which elements to keep. Implementing filter p
as a "simple" recursive function is not too hard.
filter p =
filter p (x:xs) = if p x then x : (filter p xs) else (filter p xs)
The 1st line implies e =
. The 2nd line needs to be written in the form f x (filter p xs)
to match the equation of h
above, in order for us to deduce which f
to plug in the foldr
. To do that we just abstract over those two expressions.
filter p =
filter p (x:xs) = (x ys -> if p x then x : ys else ys) x (filter p xs)
So we have found that,
e =
f x ys = if p x then x: ys else ys
It therefore follows,
filter p = foldr (y ys -> if p y then y : ys else ys)
To learn more about this method of working with foldr
I recommend reading
"A tutorial on the universality and expressiveness of fold" by Graham Hutton.
Some added notes:
In case this seems overly complicated, note that while the principles above can be used in this "semi rigorous" fashion via algebraic manipulation, they can and should also be used to guide your intuition and aid you in informal development.
The equation for h (x:xs) = f x (h xs)
sheds some clarity on how to find f
. In the case where h
is the filtering function you want an f
which combines the element x
with a tail that has already been filtered. If you really understand this it should be easy to arrive at,
f x ys = if p x then x : ys else ys
Rather than merely searching for a more elegant implementation, it would might help you more to learn an elegant process of searching for an implementation. This should make it simpler to find elegant solutions.
For any function h
on lists we have that,
h = foldr f e
if and only if
h = e
h (x:xs) = f x (h xs)
In this case your h
is filter p
for some boolean function p
that selects which elements to keep. Implementing filter p
as a "simple" recursive function is not too hard.
filter p =
filter p (x:xs) = if p x then x : (filter p xs) else (filter p xs)
The 1st line implies e =
. The 2nd line needs to be written in the form f x (filter p xs)
to match the equation of h
above, in order for us to deduce which f
to plug in the foldr
. To do that we just abstract over those two expressions.
filter p =
filter p (x:xs) = (x ys -> if p x then x : ys else ys) x (filter p xs)
So we have found that,
e =
f x ys = if p x then x: ys else ys
It therefore follows,
filter p = foldr (y ys -> if p y then y : ys else ys)
To learn more about this method of working with foldr
I recommend reading
"A tutorial on the universality and expressiveness of fold" by Graham Hutton.
Some added notes:
In case this seems overly complicated, note that while the principles above can be used in this "semi rigorous" fashion via algebraic manipulation, they can and should also be used to guide your intuition and aid you in informal development.
The equation for h (x:xs) = f x (h xs)
sheds some clarity on how to find f
. In the case where h
is the filtering function you want an f
which combines the element x
with a tail that has already been filtered. If you really understand this it should be easy to arrive at,
f x ys = if p x then x : ys else ys
edited Nov 8 at 19:47
answered Nov 8 at 12:56
Jorge Adriano
43624
43624
1
did you perhaps meanf y ys = if p y then y : ys else ys
in the last line? BTW it can also be writtenf y ys = [y | p y] ++ ys
.
– Will Ness
Nov 8 at 15:48
ops missed that, I thought x would be clearer in that context but forgot to change the p y to p x
– Jorge Adriano
Nov 8 at 17:19
I also sensed some Richard Bird in there, esp. at the start, from his "theory of lists"... :) is it so?
– Will Ness
Nov 8 at 17:24
Possibly, since my very first book on Haskell was his classic "Introduction to Functional Programming using Haskell", but never read that particular paper to be honest.
– Jorge Adriano
Nov 8 at 17:52
add a comment |
1
did you perhaps meanf y ys = if p y then y : ys else ys
in the last line? BTW it can also be writtenf y ys = [y | p y] ++ ys
.
– Will Ness
Nov 8 at 15:48
ops missed that, I thought x would be clearer in that context but forgot to change the p y to p x
– Jorge Adriano
Nov 8 at 17:19
I also sensed some Richard Bird in there, esp. at the start, from his "theory of lists"... :) is it so?
– Will Ness
Nov 8 at 17:24
Possibly, since my very first book on Haskell was his classic "Introduction to Functional Programming using Haskell", but never read that particular paper to be honest.
– Jorge Adriano
Nov 8 at 17:52
1
1
did you perhaps mean
f y ys = if p y then y : ys else ys
in the last line? BTW it can also be written f y ys = [y | p y] ++ ys
.– Will Ness
Nov 8 at 15:48
did you perhaps mean
f y ys = if p y then y : ys else ys
in the last line? BTW it can also be written f y ys = [y | p y] ++ ys
.– Will Ness
Nov 8 at 15:48
ops missed that, I thought x would be clearer in that context but forgot to change the p y to p x
– Jorge Adriano
Nov 8 at 17:19
ops missed that, I thought x would be clearer in that context but forgot to change the p y to p x
– Jorge Adriano
Nov 8 at 17:19
I also sensed some Richard Bird in there, esp. at the start, from his "theory of lists"... :) is it so?
– Will Ness
Nov 8 at 17:24
I also sensed some Richard Bird in there, esp. at the start, from his "theory of lists"... :) is it so?
– Will Ness
Nov 8 at 17:24
Possibly, since my very first book on Haskell was his classic "Introduction to Functional Programming using Haskell", but never read that particular paper to be honest.
– Jorge Adriano
Nov 8 at 17:52
Possibly, since my very first book on Haskell was his classic "Introduction to Functional Programming using Haskell", but never read that particular paper to be honest.
– Jorge Adriano
Nov 8 at 17:52
add a comment |
up vote
0
down vote
Yes, there is:
myFilter :: (a -> Bool) -> [a] -> [a]
myFilter f = foldMap (x -> [x | f x])
> myFilter even [1..10]
[2,4,6,8,10]
See, I switched it on you, with foldMap
.
Well, with foldr
it is foldr (x -> ([x | f x] ++))
.
add a comment |
up vote
0
down vote
Yes, there is:
myFilter :: (a -> Bool) -> [a] -> [a]
myFilter f = foldMap (x -> [x | f x])
> myFilter even [1..10]
[2,4,6,8,10]
See, I switched it on you, with foldMap
.
Well, with foldr
it is foldr (x -> ([x | f x] ++))
.
add a comment |
up vote
0
down vote
up vote
0
down vote
Yes, there is:
myFilter :: (a -> Bool) -> [a] -> [a]
myFilter f = foldMap (x -> [x | f x])
> myFilter even [1..10]
[2,4,6,8,10]
See, I switched it on you, with foldMap
.
Well, with foldr
it is foldr (x -> ([x | f x] ++))
.
Yes, there is:
myFilter :: (a -> Bool) -> [a] -> [a]
myFilter f = foldMap (x -> [x | f x])
> myFilter even [1..10]
[2,4,6,8,10]
See, I switched it on you, with foldMap
.
Well, with foldr
it is foldr (x -> ([x | f x] ++))
.
answered Nov 8 at 17:23
Will Ness
42k467118
42k467118
add a comment |
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53197120%2fcan-my-implementation-of-filter-be-improved%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
9
(++)
is justid
.– Willem Van Onsem
Nov 7 at 20:14
3
I'm not sure anyone would find
((:) x)
less clunky than(x :)
.– chepner
Nov 7 at 20:20
@chepner I changed that one a few seconds ago lol.
– Brady Dean
Nov 7 at 20:21
1
@chepner what do you mean? (⊢ never (is clunky (notation 'prefix)))
– leftaroundabout
Nov 7 at 20:24