How to write this function in point-free style?
How to rewrite the following function in point-free style, removing the parameter x
from the definition completely (the other two may stay):
between min max x = (min < x) && (x < max)
This is not an assignment, just a question. I don't know how to proceed. I can turn it into a lambda function
between min max = x -> (min < x) && (x < max)
but this is not point-free, as x
is still there. Please help.
haskell functional-programming pointfree tacit-programming
|
show 10 more comments
How to rewrite the following function in point-free style, removing the parameter x
from the definition completely (the other two may stay):
between min max x = (min < x) && (x < max)
This is not an assignment, just a question. I don't know how to proceed. I can turn it into a lambda function
between min max = x -> (min < x) && (x < max)
but this is not point-free, as x
is still there. Please help.
haskell functional-programming pointfree tacit-programming
5
is this an assignment? what have you tried? BTW calling your values by names of built-in functions is confusing. Better useminval
andmaxval
.
– Will Ness
Nov 20 '18 at 11:19
2
You might want to look at the documentation forliftA2
in moduleControl.Applicative
– mschmidt
Nov 20 '18 at 11:56
3
There's no compelling reason to write this particular function in point-free style. This version is quite readable as-is.
– chepner
Nov 20 '18 at 14:05
4
This question is being discussed in Meta
– yivi
Nov 21 '18 at 11:54
3
OK, so after the edit, and while the new 3rd vote for deletion is not cast, what have you tried? Where exactly is your difficulty? Have you yourself tried to find a solution? What code snippets have you written? Do you know about "operator sections"? Do you know about "combinators"? (these are googlable terms). Do you know e.g. about transformingsin (cos x)
to(sin . cos) x
? Do you know about "eta reduction"?
– Will Ness
Nov 21 '18 at 15:17
|
show 10 more comments
How to rewrite the following function in point-free style, removing the parameter x
from the definition completely (the other two may stay):
between min max x = (min < x) && (x < max)
This is not an assignment, just a question. I don't know how to proceed. I can turn it into a lambda function
between min max = x -> (min < x) && (x < max)
but this is not point-free, as x
is still there. Please help.
haskell functional-programming pointfree tacit-programming
How to rewrite the following function in point-free style, removing the parameter x
from the definition completely (the other two may stay):
between min max x = (min < x) && (x < max)
This is not an assignment, just a question. I don't know how to proceed. I can turn it into a lambda function
between min max = x -> (min < x) && (x < max)
but this is not point-free, as x
is still there. Please help.
haskell functional-programming pointfree tacit-programming
haskell functional-programming pointfree tacit-programming
edited Nov 21 '18 at 16:22
Will Ness
45.5k468124
45.5k468124
asked Nov 20 '18 at 11:09
user2304996user2304996
14618
14618
5
is this an assignment? what have you tried? BTW calling your values by names of built-in functions is confusing. Better useminval
andmaxval
.
– Will Ness
Nov 20 '18 at 11:19
2
You might want to look at the documentation forliftA2
in moduleControl.Applicative
– mschmidt
Nov 20 '18 at 11:56
3
There's no compelling reason to write this particular function in point-free style. This version is quite readable as-is.
– chepner
Nov 20 '18 at 14:05
4
This question is being discussed in Meta
– yivi
Nov 21 '18 at 11:54
3
OK, so after the edit, and while the new 3rd vote for deletion is not cast, what have you tried? Where exactly is your difficulty? Have you yourself tried to find a solution? What code snippets have you written? Do you know about "operator sections"? Do you know about "combinators"? (these are googlable terms). Do you know e.g. about transformingsin (cos x)
to(sin . cos) x
? Do you know about "eta reduction"?
– Will Ness
Nov 21 '18 at 15:17
|
show 10 more comments
5
is this an assignment? what have you tried? BTW calling your values by names of built-in functions is confusing. Better useminval
andmaxval
.
– Will Ness
Nov 20 '18 at 11:19
2
You might want to look at the documentation forliftA2
in moduleControl.Applicative
– mschmidt
Nov 20 '18 at 11:56
3
There's no compelling reason to write this particular function in point-free style. This version is quite readable as-is.
– chepner
Nov 20 '18 at 14:05
4
This question is being discussed in Meta
– yivi
Nov 21 '18 at 11:54
3
OK, so after the edit, and while the new 3rd vote for deletion is not cast, what have you tried? Where exactly is your difficulty? Have you yourself tried to find a solution? What code snippets have you written? Do you know about "operator sections"? Do you know about "combinators"? (these are googlable terms). Do you know e.g. about transformingsin (cos x)
to(sin . cos) x
? Do you know about "eta reduction"?
– Will Ness
Nov 21 '18 at 15:17
5
5
is this an assignment? what have you tried? BTW calling your values by names of built-in functions is confusing. Better use
minval
and maxval
.– Will Ness
Nov 20 '18 at 11:19
is this an assignment? what have you tried? BTW calling your values by names of built-in functions is confusing. Better use
minval
and maxval
.– Will Ness
Nov 20 '18 at 11:19
2
2
You might want to look at the documentation for
liftA2
in module Control.Applicative
– mschmidt
Nov 20 '18 at 11:56
You might want to look at the documentation for
liftA2
in module Control.Applicative
– mschmidt
Nov 20 '18 at 11:56
3
3
There's no compelling reason to write this particular function in point-free style. This version is quite readable as-is.
– chepner
Nov 20 '18 at 14:05
There's no compelling reason to write this particular function in point-free style. This version is quite readable as-is.
– chepner
Nov 20 '18 at 14:05
4
4
This question is being discussed in Meta
– yivi
Nov 21 '18 at 11:54
This question is being discussed in Meta
– yivi
Nov 21 '18 at 11:54
3
3
OK, so after the edit, and while the new 3rd vote for deletion is not cast, what have you tried? Where exactly is your difficulty? Have you yourself tried to find a solution? What code snippets have you written? Do you know about "operator sections"? Do you know about "combinators"? (these are googlable terms). Do you know e.g. about transforming
sin (cos x)
to (sin . cos) x
? Do you know about "eta reduction"?– Will Ness
Nov 21 '18 at 15:17
OK, so after the edit, and while the new 3rd vote for deletion is not cast, what have you tried? Where exactly is your difficulty? Have you yourself tried to find a solution? What code snippets have you written? Do you know about "operator sections"? Do you know about "combinators"? (these are googlable terms). Do you know e.g. about transforming
sin (cos x)
to (sin . cos) x
? Do you know about "eta reduction"?– Will Ness
Nov 21 '18 at 15:17
|
show 10 more comments
4 Answers
4
active
oldest
votes
Another solution (needs import of Control.Applicative
):
between min max = liftA2 (&&) (min <) (max >)
1
and with(<&&>) = liftA2 (&&)
it becomes the almost readable(min <) <&&> (max >)
. BTW there are these definitions somewhere,(<^) = flip fmap
and(^>) = (<*>)
, such that it becomes the nearly identical-looking(min <) <^(&&)^> (max >)
.
– Will Ness
Nov 21 '18 at 11:18
add a comment |
It can be done using the Reader
applicative:
between min max = x. (min < x) && (x < max)
{ Convert infix comparisons to sections }
= x. ((min <) x) && ((< max) x)
{ Move infix (&&) to applicative style }
= x. (&&) ((min <) x) ((< max) x)
{ Lift to applicative style using the applicative instance of `(->) a` }
= x. (pure (&&) <*> (min <) <*> (< max)) x
{ Eta-reduce }
= pure (&&) <*> (min <) <*> (< max)
{ Optionally simplify for idiomatic style }
= (&&) <$> (min <) <*> (< max)
add a comment |
Using Control.Arrow
we can reach this nearly obfuscated code:
(min <) &&& (< max) >>> uncurry (&&)
This relies on the predefined >>>
for left-to-right composition, f &&& g = x -> (f x, g x)
, and uncurrying.
pointfree.io also suggests the following unreadable code:
between = (. flip (<)) . ap . ((&&) .) . (<)
It almost seems like you're trying to discourage point-free style here :)
– chepner
Nov 20 '18 at 14:04
well,flip (<)
is the same as(>)
, so you can save a few characters there ;)
– M. Aroosi
Nov 20 '18 at 17:56
Alternatively and even shorter:liftA2 (&&) (min <) (max >)
– mschmidt
Nov 20 '18 at 18:30
@chepner I'm trying my best :) Actually, I'm in favor of point-free but against point-less. The main issue is that the difference between those can be quite subtle.
– chi
Nov 20 '18 at 19:14
1
also,and . sequence [(min <), (max >)]
.
– Will Ness
Nov 21 '18 at 15:23
add a comment |
By operator sections transformation,
between min max x = (min < x) && (x < max)
= ((&&) . (min <)) x ((< max) x)
Now this fits a pattern for S-combinator, S f g x = (f x) (g x)
. There are many ways of encoding it in Haskell, but the main two are via Applicative and via Arrows:
_S f g x = (f x) (g x)
= (f <*> g) x
= uncurry id . (f &&& g) $ x
The second gives us
between a z = uncurry (&&) . ((a <) &&& (< z))
And the first, even more fitting
between a z = (&&) <$> (a <) <*> (< z)
= liftA2 (&&) (a <) (< z)
= (a <) <^(&&)^> (< z) -- nice and visual
(<^) = flip (<$>)
(^>) = (<*>)
But we could also fiddle with other combinators, with much less satisfactory results though,
_S f g x = f x (g x)
= flip f (g x) x
= (flip f . g) x x
= join (flip f <$> g) x
= (flip f =<< g) x
or
= (f x . g) x
= (. g) (f x) x
= ((. g) =<< f) x
which illustrates nicely the dangers of pointlessness in the pursuit of the pointfree.
There's one more possibility that makes sense (syntactically), which is
_S f g x = (f x) (g x)
-- = foldr1 ($) . sequence [f,g] $ x -- not valid Haskell
-- sequence [f,g] x = [f x,g x]
This is not a valid Haskell in general because of the typing issues, but in our specific case it does give rise to one more valid definition, which also does seem to follow the inner logic of it nicely,
between a z = -- foldr1 ($) . sequence [(&&).(a <), (< z)] -- not OK
= foldr1 (&&) . sequence [(a <), (< z)] -- OK
= and . sequence [(a <), (> z)]
because (a <)
and (> z)
have the same type.
add a comment |
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/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
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%2f53391699%2fhow-to-write-this-function-in-point-free-style%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
Another solution (needs import of Control.Applicative
):
between min max = liftA2 (&&) (min <) (max >)
1
and with(<&&>) = liftA2 (&&)
it becomes the almost readable(min <) <&&> (max >)
. BTW there are these definitions somewhere,(<^) = flip fmap
and(^>) = (<*>)
, such that it becomes the nearly identical-looking(min <) <^(&&)^> (max >)
.
– Will Ness
Nov 21 '18 at 11:18
add a comment |
Another solution (needs import of Control.Applicative
):
between min max = liftA2 (&&) (min <) (max >)
1
and with(<&&>) = liftA2 (&&)
it becomes the almost readable(min <) <&&> (max >)
. BTW there are these definitions somewhere,(<^) = flip fmap
and(^>) = (<*>)
, such that it becomes the nearly identical-looking(min <) <^(&&)^> (max >)
.
– Will Ness
Nov 21 '18 at 11:18
add a comment |
Another solution (needs import of Control.Applicative
):
between min max = liftA2 (&&) (min <) (max >)
Another solution (needs import of Control.Applicative
):
between min max = liftA2 (&&) (min <) (max >)
edited Nov 20 '18 at 20:58
answered Nov 20 '18 at 18:34
mschmidtmschmidt
1,96941019
1,96941019
1
and with(<&&>) = liftA2 (&&)
it becomes the almost readable(min <) <&&> (max >)
. BTW there are these definitions somewhere,(<^) = flip fmap
and(^>) = (<*>)
, such that it becomes the nearly identical-looking(min <) <^(&&)^> (max >)
.
– Will Ness
Nov 21 '18 at 11:18
add a comment |
1
and with(<&&>) = liftA2 (&&)
it becomes the almost readable(min <) <&&> (max >)
. BTW there are these definitions somewhere,(<^) = flip fmap
and(^>) = (<*>)
, such that it becomes the nearly identical-looking(min <) <^(&&)^> (max >)
.
– Will Ness
Nov 21 '18 at 11:18
1
1
and with
(<&&>) = liftA2 (&&)
it becomes the almost readable (min <) <&&> (max >)
. BTW there are these definitions somewhere, (<^) = flip fmap
and (^>) = (<*>)
, such that it becomes the nearly identical-looking (min <) <^(&&)^> (max >)
.– Will Ness
Nov 21 '18 at 11:18
and with
(<&&>) = liftA2 (&&)
it becomes the almost readable (min <) <&&> (max >)
. BTW there are these definitions somewhere, (<^) = flip fmap
and (^>) = (<*>)
, such that it becomes the nearly identical-looking (min <) <^(&&)^> (max >)
.– Will Ness
Nov 21 '18 at 11:18
add a comment |
It can be done using the Reader
applicative:
between min max = x. (min < x) && (x < max)
{ Convert infix comparisons to sections }
= x. ((min <) x) && ((< max) x)
{ Move infix (&&) to applicative style }
= x. (&&) ((min <) x) ((< max) x)
{ Lift to applicative style using the applicative instance of `(->) a` }
= x. (pure (&&) <*> (min <) <*> (< max)) x
{ Eta-reduce }
= pure (&&) <*> (min <) <*> (< max)
{ Optionally simplify for idiomatic style }
= (&&) <$> (min <) <*> (< max)
add a comment |
It can be done using the Reader
applicative:
between min max = x. (min < x) && (x < max)
{ Convert infix comparisons to sections }
= x. ((min <) x) && ((< max) x)
{ Move infix (&&) to applicative style }
= x. (&&) ((min <) x) ((< max) x)
{ Lift to applicative style using the applicative instance of `(->) a` }
= x. (pure (&&) <*> (min <) <*> (< max)) x
{ Eta-reduce }
= pure (&&) <*> (min <) <*> (< max)
{ Optionally simplify for idiomatic style }
= (&&) <$> (min <) <*> (< max)
add a comment |
It can be done using the Reader
applicative:
between min max = x. (min < x) && (x < max)
{ Convert infix comparisons to sections }
= x. ((min <) x) && ((< max) x)
{ Move infix (&&) to applicative style }
= x. (&&) ((min <) x) ((< max) x)
{ Lift to applicative style using the applicative instance of `(->) a` }
= x. (pure (&&) <*> (min <) <*> (< max)) x
{ Eta-reduce }
= pure (&&) <*> (min <) <*> (< max)
{ Optionally simplify for idiomatic style }
= (&&) <$> (min <) <*> (< max)
It can be done using the Reader
applicative:
between min max = x. (min < x) && (x < max)
{ Convert infix comparisons to sections }
= x. ((min <) x) && ((< max) x)
{ Move infix (&&) to applicative style }
= x. (&&) ((min <) x) ((< max) x)
{ Lift to applicative style using the applicative instance of `(->) a` }
= x. (pure (&&) <*> (min <) <*> (< max)) x
{ Eta-reduce }
= pure (&&) <*> (min <) <*> (< max)
{ Optionally simplify for idiomatic style }
= (&&) <$> (min <) <*> (< max)
answered Nov 20 '18 at 11:27
KrisKris
635313
635313
add a comment |
add a comment |
Using Control.Arrow
we can reach this nearly obfuscated code:
(min <) &&& (< max) >>> uncurry (&&)
This relies on the predefined >>>
for left-to-right composition, f &&& g = x -> (f x, g x)
, and uncurrying.
pointfree.io also suggests the following unreadable code:
between = (. flip (<)) . ap . ((&&) .) . (<)
It almost seems like you're trying to discourage point-free style here :)
– chepner
Nov 20 '18 at 14:04
well,flip (<)
is the same as(>)
, so you can save a few characters there ;)
– M. Aroosi
Nov 20 '18 at 17:56
Alternatively and even shorter:liftA2 (&&) (min <) (max >)
– mschmidt
Nov 20 '18 at 18:30
@chepner I'm trying my best :) Actually, I'm in favor of point-free but against point-less. The main issue is that the difference between those can be quite subtle.
– chi
Nov 20 '18 at 19:14
1
also,and . sequence [(min <), (max >)]
.
– Will Ness
Nov 21 '18 at 15:23
add a comment |
Using Control.Arrow
we can reach this nearly obfuscated code:
(min <) &&& (< max) >>> uncurry (&&)
This relies on the predefined >>>
for left-to-right composition, f &&& g = x -> (f x, g x)
, and uncurrying.
pointfree.io also suggests the following unreadable code:
between = (. flip (<)) . ap . ((&&) .) . (<)
It almost seems like you're trying to discourage point-free style here :)
– chepner
Nov 20 '18 at 14:04
well,flip (<)
is the same as(>)
, so you can save a few characters there ;)
– M. Aroosi
Nov 20 '18 at 17:56
Alternatively and even shorter:liftA2 (&&) (min <) (max >)
– mschmidt
Nov 20 '18 at 18:30
@chepner I'm trying my best :) Actually, I'm in favor of point-free but against point-less. The main issue is that the difference between those can be quite subtle.
– chi
Nov 20 '18 at 19:14
1
also,and . sequence [(min <), (max >)]
.
– Will Ness
Nov 21 '18 at 15:23
add a comment |
Using Control.Arrow
we can reach this nearly obfuscated code:
(min <) &&& (< max) >>> uncurry (&&)
This relies on the predefined >>>
for left-to-right composition, f &&& g = x -> (f x, g x)
, and uncurrying.
pointfree.io also suggests the following unreadable code:
between = (. flip (<)) . ap . ((&&) .) . (<)
Using Control.Arrow
we can reach this nearly obfuscated code:
(min <) &&& (< max) >>> uncurry (&&)
This relies on the predefined >>>
for left-to-right composition, f &&& g = x -> (f x, g x)
, and uncurrying.
pointfree.io also suggests the following unreadable code:
between = (. flip (<)) . ap . ((&&) .) . (<)
edited Nov 20 '18 at 13:56
answered Nov 20 '18 at 13:42
chichi
74.6k284140
74.6k284140
It almost seems like you're trying to discourage point-free style here :)
– chepner
Nov 20 '18 at 14:04
well,flip (<)
is the same as(>)
, so you can save a few characters there ;)
– M. Aroosi
Nov 20 '18 at 17:56
Alternatively and even shorter:liftA2 (&&) (min <) (max >)
– mschmidt
Nov 20 '18 at 18:30
@chepner I'm trying my best :) Actually, I'm in favor of point-free but against point-less. The main issue is that the difference between those can be quite subtle.
– chi
Nov 20 '18 at 19:14
1
also,and . sequence [(min <), (max >)]
.
– Will Ness
Nov 21 '18 at 15:23
add a comment |
It almost seems like you're trying to discourage point-free style here :)
– chepner
Nov 20 '18 at 14:04
well,flip (<)
is the same as(>)
, so you can save a few characters there ;)
– M. Aroosi
Nov 20 '18 at 17:56
Alternatively and even shorter:liftA2 (&&) (min <) (max >)
– mschmidt
Nov 20 '18 at 18:30
@chepner I'm trying my best :) Actually, I'm in favor of point-free but against point-less. The main issue is that the difference between those can be quite subtle.
– chi
Nov 20 '18 at 19:14
1
also,and . sequence [(min <), (max >)]
.
– Will Ness
Nov 21 '18 at 15:23
It almost seems like you're trying to discourage point-free style here :)
– chepner
Nov 20 '18 at 14:04
It almost seems like you're trying to discourage point-free style here :)
– chepner
Nov 20 '18 at 14:04
well,
flip (<)
is the same as (>)
, so you can save a few characters there ;)– M. Aroosi
Nov 20 '18 at 17:56
well,
flip (<)
is the same as (>)
, so you can save a few characters there ;)– M. Aroosi
Nov 20 '18 at 17:56
Alternatively and even shorter:
liftA2 (&&) (min <) (max >)
– mschmidt
Nov 20 '18 at 18:30
Alternatively and even shorter:
liftA2 (&&) (min <) (max >)
– mschmidt
Nov 20 '18 at 18:30
@chepner I'm trying my best :) Actually, I'm in favor of point-free but against point-less. The main issue is that the difference between those can be quite subtle.
– chi
Nov 20 '18 at 19:14
@chepner I'm trying my best :) Actually, I'm in favor of point-free but against point-less. The main issue is that the difference between those can be quite subtle.
– chi
Nov 20 '18 at 19:14
1
1
also,
and . sequence [(min <), (max >)]
.– Will Ness
Nov 21 '18 at 15:23
also,
and . sequence [(min <), (max >)]
.– Will Ness
Nov 21 '18 at 15:23
add a comment |
By operator sections transformation,
between min max x = (min < x) && (x < max)
= ((&&) . (min <)) x ((< max) x)
Now this fits a pattern for S-combinator, S f g x = (f x) (g x)
. There are many ways of encoding it in Haskell, but the main two are via Applicative and via Arrows:
_S f g x = (f x) (g x)
= (f <*> g) x
= uncurry id . (f &&& g) $ x
The second gives us
between a z = uncurry (&&) . ((a <) &&& (< z))
And the first, even more fitting
between a z = (&&) <$> (a <) <*> (< z)
= liftA2 (&&) (a <) (< z)
= (a <) <^(&&)^> (< z) -- nice and visual
(<^) = flip (<$>)
(^>) = (<*>)
But we could also fiddle with other combinators, with much less satisfactory results though,
_S f g x = f x (g x)
= flip f (g x) x
= (flip f . g) x x
= join (flip f <$> g) x
= (flip f =<< g) x
or
= (f x . g) x
= (. g) (f x) x
= ((. g) =<< f) x
which illustrates nicely the dangers of pointlessness in the pursuit of the pointfree.
There's one more possibility that makes sense (syntactically), which is
_S f g x = (f x) (g x)
-- = foldr1 ($) . sequence [f,g] $ x -- not valid Haskell
-- sequence [f,g] x = [f x,g x]
This is not a valid Haskell in general because of the typing issues, but in our specific case it does give rise to one more valid definition, which also does seem to follow the inner logic of it nicely,
between a z = -- foldr1 ($) . sequence [(&&).(a <), (< z)] -- not OK
= foldr1 (&&) . sequence [(a <), (< z)] -- OK
= and . sequence [(a <), (> z)]
because (a <)
and (> z)
have the same type.
add a comment |
By operator sections transformation,
between min max x = (min < x) && (x < max)
= ((&&) . (min <)) x ((< max) x)
Now this fits a pattern for S-combinator, S f g x = (f x) (g x)
. There are many ways of encoding it in Haskell, but the main two are via Applicative and via Arrows:
_S f g x = (f x) (g x)
= (f <*> g) x
= uncurry id . (f &&& g) $ x
The second gives us
between a z = uncurry (&&) . ((a <) &&& (< z))
And the first, even more fitting
between a z = (&&) <$> (a <) <*> (< z)
= liftA2 (&&) (a <) (< z)
= (a <) <^(&&)^> (< z) -- nice and visual
(<^) = flip (<$>)
(^>) = (<*>)
But we could also fiddle with other combinators, with much less satisfactory results though,
_S f g x = f x (g x)
= flip f (g x) x
= (flip f . g) x x
= join (flip f <$> g) x
= (flip f =<< g) x
or
= (f x . g) x
= (. g) (f x) x
= ((. g) =<< f) x
which illustrates nicely the dangers of pointlessness in the pursuit of the pointfree.
There's one more possibility that makes sense (syntactically), which is
_S f g x = (f x) (g x)
-- = foldr1 ($) . sequence [f,g] $ x -- not valid Haskell
-- sequence [f,g] x = [f x,g x]
This is not a valid Haskell in general because of the typing issues, but in our specific case it does give rise to one more valid definition, which also does seem to follow the inner logic of it nicely,
between a z = -- foldr1 ($) . sequence [(&&).(a <), (< z)] -- not OK
= foldr1 (&&) . sequence [(a <), (< z)] -- OK
= and . sequence [(a <), (> z)]
because (a <)
and (> z)
have the same type.
add a comment |
By operator sections transformation,
between min max x = (min < x) && (x < max)
= ((&&) . (min <)) x ((< max) x)
Now this fits a pattern for S-combinator, S f g x = (f x) (g x)
. There are many ways of encoding it in Haskell, but the main two are via Applicative and via Arrows:
_S f g x = (f x) (g x)
= (f <*> g) x
= uncurry id . (f &&& g) $ x
The second gives us
between a z = uncurry (&&) . ((a <) &&& (< z))
And the first, even more fitting
between a z = (&&) <$> (a <) <*> (< z)
= liftA2 (&&) (a <) (< z)
= (a <) <^(&&)^> (< z) -- nice and visual
(<^) = flip (<$>)
(^>) = (<*>)
But we could also fiddle with other combinators, with much less satisfactory results though,
_S f g x = f x (g x)
= flip f (g x) x
= (flip f . g) x x
= join (flip f <$> g) x
= (flip f =<< g) x
or
= (f x . g) x
= (. g) (f x) x
= ((. g) =<< f) x
which illustrates nicely the dangers of pointlessness in the pursuit of the pointfree.
There's one more possibility that makes sense (syntactically), which is
_S f g x = (f x) (g x)
-- = foldr1 ($) . sequence [f,g] $ x -- not valid Haskell
-- sequence [f,g] x = [f x,g x]
This is not a valid Haskell in general because of the typing issues, but in our specific case it does give rise to one more valid definition, which also does seem to follow the inner logic of it nicely,
between a z = -- foldr1 ($) . sequence [(&&).(a <), (< z)] -- not OK
= foldr1 (&&) . sequence [(a <), (< z)] -- OK
= and . sequence [(a <), (> z)]
because (a <)
and (> z)
have the same type.
By operator sections transformation,
between min max x = (min < x) && (x < max)
= ((&&) . (min <)) x ((< max) x)
Now this fits a pattern for S-combinator, S f g x = (f x) (g x)
. There are many ways of encoding it in Haskell, but the main two are via Applicative and via Arrows:
_S f g x = (f x) (g x)
= (f <*> g) x
= uncurry id . (f &&& g) $ x
The second gives us
between a z = uncurry (&&) . ((a <) &&& (< z))
And the first, even more fitting
between a z = (&&) <$> (a <) <*> (< z)
= liftA2 (&&) (a <) (< z)
= (a <) <^(&&)^> (< z) -- nice and visual
(<^) = flip (<$>)
(^>) = (<*>)
But we could also fiddle with other combinators, with much less satisfactory results though,
_S f g x = f x (g x)
= flip f (g x) x
= (flip f . g) x x
= join (flip f <$> g) x
= (flip f =<< g) x
or
= (f x . g) x
= (. g) (f x) x
= ((. g) =<< f) x
which illustrates nicely the dangers of pointlessness in the pursuit of the pointfree.
There's one more possibility that makes sense (syntactically), which is
_S f g x = (f x) (g x)
-- = foldr1 ($) . sequence [f,g] $ x -- not valid Haskell
-- sequence [f,g] x = [f x,g x]
This is not a valid Haskell in general because of the typing issues, but in our specific case it does give rise to one more valid definition, which also does seem to follow the inner logic of it nicely,
between a z = -- foldr1 ($) . sequence [(&&).(a <), (< z)] -- not OK
= foldr1 (&&) . sequence [(a <), (< z)] -- OK
= and . sequence [(a <), (> z)]
because (a <)
and (> z)
have the same type.
answered Nov 23 '18 at 10:16
Will NessWill Ness
45.5k468124
45.5k468124
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
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%2f53391699%2fhow-to-write-this-function-in-point-free-style%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
5
is this an assignment? what have you tried? BTW calling your values by names of built-in functions is confusing. Better use
minval
andmaxval
.– Will Ness
Nov 20 '18 at 11:19
2
You might want to look at the documentation for
liftA2
in moduleControl.Applicative
– mschmidt
Nov 20 '18 at 11:56
3
There's no compelling reason to write this particular function in point-free style. This version is quite readable as-is.
– chepner
Nov 20 '18 at 14:05
4
This question is being discussed in Meta
– yivi
Nov 21 '18 at 11:54
3
OK, so after the edit, and while the new 3rd vote for deletion is not cast, what have you tried? Where exactly is your difficulty? Have you yourself tried to find a solution? What code snippets have you written? Do you know about "operator sections"? Do you know about "combinators"? (these are googlable terms). Do you know e.g. about transforming
sin (cos x)
to(sin . cos) x
? Do you know about "eta reduction"?– Will Ness
Nov 21 '18 at 15:17