Transforming a function in Haskell to point free notation











up vote
5
down vote

favorite
1












I have a function in haskell on paper as an example:



function2 a b c = (a * b) + c 


and I'm required to write the example in point free notation. I'm really bad at working with point free style as I find it really confusing with no proper guide through it so i gave it a try:



function2 a b c = (a * b) + c
function2 a b c = ((*) a b) + c #operator sectioning
function2 a b c = (+) ((*) a b)c #operator sectioning once more
#I'm stuck here now


I wasnt sure what should come up next as that was the limit i could think of for this example. Would appreciate some help on this.



--Second example:



function3 a b = a `div` (g b)
function3 a b = `div` a (g b) --operator sectioning
function3 a b = (`div` a) (g b) --parentheses
function3 a b = ((`div` a g).)b --B combinator
function3 a = ((`div` a g).) --eta conversion
function3 a = ((.)(`div` a g)) --operator sectioning
function3 a = ((.)flip(`div` g a))
function3 a = ((.)flip(`div` g).a) --B combinator
function3 = ((.)flip(`div` g)) --eta conversion (complete)









share|improve this question
























  • please ask your new question in a separate post, and include a link to this post for reference if you like. I'll rollback your last edit, please don't take it as a slight. :) It's just how SO is supposed to work. and yes, there is an error in your new derivation chain, pretty near the start, which invalidates all the steps after it.
    – Will Ness
    Nov 4 at 9:48












  • or actually, I might have been mistaken there. if you'd ask it, it could conceivably be closed as a duplicate. I restored it.
    – Will Ness
    Nov 4 at 9:50

















up vote
5
down vote

favorite
1












I have a function in haskell on paper as an example:



function2 a b c = (a * b) + c 


and I'm required to write the example in point free notation. I'm really bad at working with point free style as I find it really confusing with no proper guide through it so i gave it a try:



function2 a b c = (a * b) + c
function2 a b c = ((*) a b) + c #operator sectioning
function2 a b c = (+) ((*) a b)c #operator sectioning once more
#I'm stuck here now


I wasnt sure what should come up next as that was the limit i could think of for this example. Would appreciate some help on this.



--Second example:



function3 a b = a `div` (g b)
function3 a b = `div` a (g b) --operator sectioning
function3 a b = (`div` a) (g b) --parentheses
function3 a b = ((`div` a g).)b --B combinator
function3 a = ((`div` a g).) --eta conversion
function3 a = ((.)(`div` a g)) --operator sectioning
function3 a = ((.)flip(`div` g a))
function3 a = ((.)flip(`div` g).a) --B combinator
function3 = ((.)flip(`div` g)) --eta conversion (complete)









share|improve this question
























  • please ask your new question in a separate post, and include a link to this post for reference if you like. I'll rollback your last edit, please don't take it as a slight. :) It's just how SO is supposed to work. and yes, there is an error in your new derivation chain, pretty near the start, which invalidates all the steps after it.
    – Will Ness
    Nov 4 at 9:48












  • or actually, I might have been mistaken there. if you'd ask it, it could conceivably be closed as a duplicate. I restored it.
    – Will Ness
    Nov 4 at 9:50















up vote
5
down vote

favorite
1









up vote
5
down vote

favorite
1






1





I have a function in haskell on paper as an example:



function2 a b c = (a * b) + c 


and I'm required to write the example in point free notation. I'm really bad at working with point free style as I find it really confusing with no proper guide through it so i gave it a try:



function2 a b c = (a * b) + c
function2 a b c = ((*) a b) + c #operator sectioning
function2 a b c = (+) ((*) a b)c #operator sectioning once more
#I'm stuck here now


I wasnt sure what should come up next as that was the limit i could think of for this example. Would appreciate some help on this.



--Second example:



function3 a b = a `div` (g b)
function3 a b = `div` a (g b) --operator sectioning
function3 a b = (`div` a) (g b) --parentheses
function3 a b = ((`div` a g).)b --B combinator
function3 a = ((`div` a g).) --eta conversion
function3 a = ((.)(`div` a g)) --operator sectioning
function3 a = ((.)flip(`div` g a))
function3 a = ((.)flip(`div` g).a) --B combinator
function3 = ((.)flip(`div` g)) --eta conversion (complete)









share|improve this question















I have a function in haskell on paper as an example:



function2 a b c = (a * b) + c 


and I'm required to write the example in point free notation. I'm really bad at working with point free style as I find it really confusing with no proper guide through it so i gave it a try:



function2 a b c = (a * b) + c
function2 a b c = ((*) a b) + c #operator sectioning
function2 a b c = (+) ((*) a b)c #operator sectioning once more
#I'm stuck here now


I wasnt sure what should come up next as that was the limit i could think of for this example. Would appreciate some help on this.



--Second example:



function3 a b = a `div` (g b)
function3 a b = `div` a (g b) --operator sectioning
function3 a b = (`div` a) (g b) --parentheses
function3 a b = ((`div` a g).)b --B combinator
function3 a = ((`div` a g).) --eta conversion
function3 a = ((.)(`div` a g)) --operator sectioning
function3 a = ((.)flip(`div` g a))
function3 a = ((.)flip(`div` g).a) --B combinator
function3 = ((.)flip(`div` g)) --eta conversion (complete)






haskell pointfree






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 4 at 9:50









Will Ness

41.8k466118




41.8k466118










asked Nov 2 at 9:46









jazzer97

483




483












  • please ask your new question in a separate post, and include a link to this post for reference if you like. I'll rollback your last edit, please don't take it as a slight. :) It's just how SO is supposed to work. and yes, there is an error in your new derivation chain, pretty near the start, which invalidates all the steps after it.
    – Will Ness
    Nov 4 at 9:48












  • or actually, I might have been mistaken there. if you'd ask it, it could conceivably be closed as a duplicate. I restored it.
    – Will Ness
    Nov 4 at 9:50




















  • please ask your new question in a separate post, and include a link to this post for reference if you like. I'll rollback your last edit, please don't take it as a slight. :) It's just how SO is supposed to work. and yes, there is an error in your new derivation chain, pretty near the start, which invalidates all the steps after it.
    – Will Ness
    Nov 4 at 9:48












  • or actually, I might have been mistaken there. if you'd ask it, it could conceivably be closed as a duplicate. I restored it.
    – Will Ness
    Nov 4 at 9:50


















please ask your new question in a separate post, and include a link to this post for reference if you like. I'll rollback your last edit, please don't take it as a slight. :) It's just how SO is supposed to work. and yes, there is an error in your new derivation chain, pretty near the start, which invalidates all the steps after it.
– Will Ness
Nov 4 at 9:48






please ask your new question in a separate post, and include a link to this post for reference if you like. I'll rollback your last edit, please don't take it as a slight. :) It's just how SO is supposed to work. and yes, there is an error in your new derivation chain, pretty near the start, which invalidates all the steps after it.
– Will Ness
Nov 4 at 9:48














or actually, I might have been mistaken there. if you'd ask it, it could conceivably be closed as a duplicate. I restored it.
– Will Ness
Nov 4 at 9:50






or actually, I might have been mistaken there. if you'd ask it, it could conceivably be closed as a duplicate. I restored it.
– Will Ness
Nov 4 at 9:50














2 Answers
2






active

oldest

votes

















up vote
5
down vote



accepted










You can apply the B combinator (i.e. (f . g) x = f (g x)) there:



function2 a b c = (a * b) + c
function2 a b c = ((*) a b) + c -- operator sectioning
function2 a b c = (+) ((*) a b) c -- operator sectioning once more
= (+) (((*) a) b) c -- explicit parentheses
= ((+) . ((*) a)) b c -- B combinator
= ((.) (+) ((*) a)) b c -- operator sectioning
= ((.) (+) . (*)) a b c -- B combinator


Indeed the types are the same:



> :t let function2 a b c = (a * b) + c in function2
let function2 a b c = (a * b) + c in function2
:: Num a => a -> a -> a -> a

> :t ((.) (+) . (*))
((.) (+) . (*)) :: Num b => b -> b -> b -> b


We work by extricating the arguments one by one in the correct order, to end up with



function2 a b c = (......) a b c


so that the eta-contraction can be applied to get rid of the explicit arguments,



function2       = (......) 


Our tools in this, which we get to apply in both directions, are



S a b c  =  (a c) (b c)  =  (a <*> b) c
K a b = a = const a b
I a = a = id a
B a b c = a (b c) = (a . b) c
C a b c = a c b = flip a b c
W a b = a b b = join a b
U a = a a -- not in Haskell: `join id` has no type


There's also (f =<< g) x = f (g x) x = join (f . g) x.



Some more, useful patterns that emerge when we work with pointfree for a while are:



((f .) .) g x y = f (g x y)
(((f .) .) .) g x y z = f (g x y z)
.....
((. g) . f) x y = f x (g y)
((. g) . f . h) x y = f (h x) (g y)




(update.) There's an error near the start in your second example, invalidating all the following steps after it:



function3 a b = a `div` (g b)
function3 a b = -- `div` a (g b) -- wrong syntax, you meant
div a (g b)
function3 a b = -- (`div` a) (g b) -- wrong; it is
(a `div`) (g b) --operator sectioning
function3 a b = ((a `div`) . g) b --B combinator
function3 a = (div a . g) --eta conversion; back with plain syntax
function3 a = (.) (div a) g --operator sectioning
function3 a = flip (.) g (div a) --definition of flip
function3 a = (flip (.) g . div) a --B combinator
function3 = (flip (.) g . div) --eta conversion
= (.) (flip (.) g) div --operator section


So yeah, some of the steps were in the right direction.






share|improve this answer























  • Sorry, I don't get it. How is ((.) (+) ((*) a)) b c = ((.) (+) . (*)) a b c? What is f and g here if this were perceived as (f . g) x = f (g x)?
    – TobiMcNamobi
    Nov 2 at 14:08






  • 1




    @TobiMcNamobi f = (.) (+) = ((.) (+)) ; g = (*) ; (f (g a)) == (f . g) a. b, c are just hanging, irrelevant for this transformation. extraneous parentheses are also irrelevant.
    – Will Ness
    Nov 2 at 14:14












  • @WillNess thanks for the thorough explanation previously. So based on it, I've worked on another example i attempted in the updated post above, would appreciate if you could assess it and inform me if I'm right with the rules.
    – jazzer97
    Nov 4 at 8:25










  • you're welcome. I'll edit the answer shortly.
    – Will Ness
    Nov 4 at 9:51










  • @WillNess thank you. One question, why is it that its div a (g b) then reverted back to (a div) (g b)? Does the ` ` play a role in the change?
    – jazzer97
    Nov 4 at 10:54


















up vote
3
down vote













We can continue with:



function2 a b = (+) ((*) a b)     [eta-reduction]
function2 a = (+) . (*) a [using a dot, to eliminate the b]
function2 = ((.) . (.)) (+) (*) ["blackbird" operator to pass two parameters]


Here the "blackbird operator" is a combination of three (.) :: (b -> c) -> (a -> b) -> a -> c operators. It is functionally equivalent to:



((.) . (.)) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
((.) . (.)) f g x y = f (g x y)


see here for a derivation.






share|improve this answer























  • I presume you’re calling it “owl” to avoid the fact that people in practice refer to it as a different kind of hooters, but in the usual aviary of combinator birds, the owl O is λfg.g(fg); this is the blackbird B₁ = λfgxy.f(gxy), sometimes spelled (.:), (...), or fmap fmap fmap if you want to be silly about it. For my pointfree code though, I prefer to just add an fmapfmap (+) . (*)—since even though it’s just composition here, semantically I think of it as “mapping over” the extra argument.
    – Jon Purdy
    Nov 2 at 19:10











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53116154%2ftransforming-a-function-in-haskell-to-point-free-notation%23new-answer', 'question_page');
}
);

Post as a guest
































2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
5
down vote



accepted










You can apply the B combinator (i.e. (f . g) x = f (g x)) there:



function2 a b c = (a * b) + c
function2 a b c = ((*) a b) + c -- operator sectioning
function2 a b c = (+) ((*) a b) c -- operator sectioning once more
= (+) (((*) a) b) c -- explicit parentheses
= ((+) . ((*) a)) b c -- B combinator
= ((.) (+) ((*) a)) b c -- operator sectioning
= ((.) (+) . (*)) a b c -- B combinator


Indeed the types are the same:



> :t let function2 a b c = (a * b) + c in function2
let function2 a b c = (a * b) + c in function2
:: Num a => a -> a -> a -> a

> :t ((.) (+) . (*))
((.) (+) . (*)) :: Num b => b -> b -> b -> b


We work by extricating the arguments one by one in the correct order, to end up with



function2 a b c = (......) a b c


so that the eta-contraction can be applied to get rid of the explicit arguments,



function2       = (......) 


Our tools in this, which we get to apply in both directions, are



S a b c  =  (a c) (b c)  =  (a <*> b) c
K a b = a = const a b
I a = a = id a
B a b c = a (b c) = (a . b) c
C a b c = a c b = flip a b c
W a b = a b b = join a b
U a = a a -- not in Haskell: `join id` has no type


There's also (f =<< g) x = f (g x) x = join (f . g) x.



Some more, useful patterns that emerge when we work with pointfree for a while are:



((f .) .) g x y = f (g x y)
(((f .) .) .) g x y z = f (g x y z)
.....
((. g) . f) x y = f x (g y)
((. g) . f . h) x y = f (h x) (g y)




(update.) There's an error near the start in your second example, invalidating all the following steps after it:



function3 a b = a `div` (g b)
function3 a b = -- `div` a (g b) -- wrong syntax, you meant
div a (g b)
function3 a b = -- (`div` a) (g b) -- wrong; it is
(a `div`) (g b) --operator sectioning
function3 a b = ((a `div`) . g) b --B combinator
function3 a = (div a . g) --eta conversion; back with plain syntax
function3 a = (.) (div a) g --operator sectioning
function3 a = flip (.) g (div a) --definition of flip
function3 a = (flip (.) g . div) a --B combinator
function3 = (flip (.) g . div) --eta conversion
= (.) (flip (.) g) div --operator section


So yeah, some of the steps were in the right direction.






share|improve this answer























  • Sorry, I don't get it. How is ((.) (+) ((*) a)) b c = ((.) (+) . (*)) a b c? What is f and g here if this were perceived as (f . g) x = f (g x)?
    – TobiMcNamobi
    Nov 2 at 14:08






  • 1




    @TobiMcNamobi f = (.) (+) = ((.) (+)) ; g = (*) ; (f (g a)) == (f . g) a. b, c are just hanging, irrelevant for this transformation. extraneous parentheses are also irrelevant.
    – Will Ness
    Nov 2 at 14:14












  • @WillNess thanks for the thorough explanation previously. So based on it, I've worked on another example i attempted in the updated post above, would appreciate if you could assess it and inform me if I'm right with the rules.
    – jazzer97
    Nov 4 at 8:25










  • you're welcome. I'll edit the answer shortly.
    – Will Ness
    Nov 4 at 9:51










  • @WillNess thank you. One question, why is it that its div a (g b) then reverted back to (a div) (g b)? Does the ` ` play a role in the change?
    – jazzer97
    Nov 4 at 10:54















up vote
5
down vote



accepted










You can apply the B combinator (i.e. (f . g) x = f (g x)) there:



function2 a b c = (a * b) + c
function2 a b c = ((*) a b) + c -- operator sectioning
function2 a b c = (+) ((*) a b) c -- operator sectioning once more
= (+) (((*) a) b) c -- explicit parentheses
= ((+) . ((*) a)) b c -- B combinator
= ((.) (+) ((*) a)) b c -- operator sectioning
= ((.) (+) . (*)) a b c -- B combinator


Indeed the types are the same:



> :t let function2 a b c = (a * b) + c in function2
let function2 a b c = (a * b) + c in function2
:: Num a => a -> a -> a -> a

> :t ((.) (+) . (*))
((.) (+) . (*)) :: Num b => b -> b -> b -> b


We work by extricating the arguments one by one in the correct order, to end up with



function2 a b c = (......) a b c


so that the eta-contraction can be applied to get rid of the explicit arguments,



function2       = (......) 


Our tools in this, which we get to apply in both directions, are



S a b c  =  (a c) (b c)  =  (a <*> b) c
K a b = a = const a b
I a = a = id a
B a b c = a (b c) = (a . b) c
C a b c = a c b = flip a b c
W a b = a b b = join a b
U a = a a -- not in Haskell: `join id` has no type


There's also (f =<< g) x = f (g x) x = join (f . g) x.



Some more, useful patterns that emerge when we work with pointfree for a while are:



((f .) .) g x y = f (g x y)
(((f .) .) .) g x y z = f (g x y z)
.....
((. g) . f) x y = f x (g y)
((. g) . f . h) x y = f (h x) (g y)




(update.) There's an error near the start in your second example, invalidating all the following steps after it:



function3 a b = a `div` (g b)
function3 a b = -- `div` a (g b) -- wrong syntax, you meant
div a (g b)
function3 a b = -- (`div` a) (g b) -- wrong; it is
(a `div`) (g b) --operator sectioning
function3 a b = ((a `div`) . g) b --B combinator
function3 a = (div a . g) --eta conversion; back with plain syntax
function3 a = (.) (div a) g --operator sectioning
function3 a = flip (.) g (div a) --definition of flip
function3 a = (flip (.) g . div) a --B combinator
function3 = (flip (.) g . div) --eta conversion
= (.) (flip (.) g) div --operator section


So yeah, some of the steps were in the right direction.






share|improve this answer























  • Sorry, I don't get it. How is ((.) (+) ((*) a)) b c = ((.) (+) . (*)) a b c? What is f and g here if this were perceived as (f . g) x = f (g x)?
    – TobiMcNamobi
    Nov 2 at 14:08






  • 1




    @TobiMcNamobi f = (.) (+) = ((.) (+)) ; g = (*) ; (f (g a)) == (f . g) a. b, c are just hanging, irrelevant for this transformation. extraneous parentheses are also irrelevant.
    – Will Ness
    Nov 2 at 14:14












  • @WillNess thanks for the thorough explanation previously. So based on it, I've worked on another example i attempted in the updated post above, would appreciate if you could assess it and inform me if I'm right with the rules.
    – jazzer97
    Nov 4 at 8:25










  • you're welcome. I'll edit the answer shortly.
    – Will Ness
    Nov 4 at 9:51










  • @WillNess thank you. One question, why is it that its div a (g b) then reverted back to (a div) (g b)? Does the ` ` play a role in the change?
    – jazzer97
    Nov 4 at 10:54













up vote
5
down vote



accepted







up vote
5
down vote



accepted






You can apply the B combinator (i.e. (f . g) x = f (g x)) there:



function2 a b c = (a * b) + c
function2 a b c = ((*) a b) + c -- operator sectioning
function2 a b c = (+) ((*) a b) c -- operator sectioning once more
= (+) (((*) a) b) c -- explicit parentheses
= ((+) . ((*) a)) b c -- B combinator
= ((.) (+) ((*) a)) b c -- operator sectioning
= ((.) (+) . (*)) a b c -- B combinator


Indeed the types are the same:



> :t let function2 a b c = (a * b) + c in function2
let function2 a b c = (a * b) + c in function2
:: Num a => a -> a -> a -> a

> :t ((.) (+) . (*))
((.) (+) . (*)) :: Num b => b -> b -> b -> b


We work by extricating the arguments one by one in the correct order, to end up with



function2 a b c = (......) a b c


so that the eta-contraction can be applied to get rid of the explicit arguments,



function2       = (......) 


Our tools in this, which we get to apply in both directions, are



S a b c  =  (a c) (b c)  =  (a <*> b) c
K a b = a = const a b
I a = a = id a
B a b c = a (b c) = (a . b) c
C a b c = a c b = flip a b c
W a b = a b b = join a b
U a = a a -- not in Haskell: `join id` has no type


There's also (f =<< g) x = f (g x) x = join (f . g) x.



Some more, useful patterns that emerge when we work with pointfree for a while are:



((f .) .) g x y = f (g x y)
(((f .) .) .) g x y z = f (g x y z)
.....
((. g) . f) x y = f x (g y)
((. g) . f . h) x y = f (h x) (g y)




(update.) There's an error near the start in your second example, invalidating all the following steps after it:



function3 a b = a `div` (g b)
function3 a b = -- `div` a (g b) -- wrong syntax, you meant
div a (g b)
function3 a b = -- (`div` a) (g b) -- wrong; it is
(a `div`) (g b) --operator sectioning
function3 a b = ((a `div`) . g) b --B combinator
function3 a = (div a . g) --eta conversion; back with plain syntax
function3 a = (.) (div a) g --operator sectioning
function3 a = flip (.) g (div a) --definition of flip
function3 a = (flip (.) g . div) a --B combinator
function3 = (flip (.) g . div) --eta conversion
= (.) (flip (.) g) div --operator section


So yeah, some of the steps were in the right direction.






share|improve this answer














You can apply the B combinator (i.e. (f . g) x = f (g x)) there:



function2 a b c = (a * b) + c
function2 a b c = ((*) a b) + c -- operator sectioning
function2 a b c = (+) ((*) a b) c -- operator sectioning once more
= (+) (((*) a) b) c -- explicit parentheses
= ((+) . ((*) a)) b c -- B combinator
= ((.) (+) ((*) a)) b c -- operator sectioning
= ((.) (+) . (*)) a b c -- B combinator


Indeed the types are the same:



> :t let function2 a b c = (a * b) + c in function2
let function2 a b c = (a * b) + c in function2
:: Num a => a -> a -> a -> a

> :t ((.) (+) . (*))
((.) (+) . (*)) :: Num b => b -> b -> b -> b


We work by extricating the arguments one by one in the correct order, to end up with



function2 a b c = (......) a b c


so that the eta-contraction can be applied to get rid of the explicit arguments,



function2       = (......) 


Our tools in this, which we get to apply in both directions, are



S a b c  =  (a c) (b c)  =  (a <*> b) c
K a b = a = const a b
I a = a = id a
B a b c = a (b c) = (a . b) c
C a b c = a c b = flip a b c
W a b = a b b = join a b
U a = a a -- not in Haskell: `join id` has no type


There's also (f =<< g) x = f (g x) x = join (f . g) x.



Some more, useful patterns that emerge when we work with pointfree for a while are:



((f .) .) g x y = f (g x y)
(((f .) .) .) g x y z = f (g x y z)
.....
((. g) . f) x y = f x (g y)
((. g) . f . h) x y = f (h x) (g y)




(update.) There's an error near the start in your second example, invalidating all the following steps after it:



function3 a b = a `div` (g b)
function3 a b = -- `div` a (g b) -- wrong syntax, you meant
div a (g b)
function3 a b = -- (`div` a) (g b) -- wrong; it is
(a `div`) (g b) --operator sectioning
function3 a b = ((a `div`) . g) b --B combinator
function3 a = (div a . g) --eta conversion; back with plain syntax
function3 a = (.) (div a) g --operator sectioning
function3 a = flip (.) g (div a) --definition of flip
function3 a = (flip (.) g . div) a --B combinator
function3 = (flip (.) g . div) --eta conversion
= (.) (flip (.) g) div --operator section


So yeah, some of the steps were in the right direction.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 4 at 10:11

























answered Nov 2 at 9:56









Will Ness

41.8k466118




41.8k466118












  • Sorry, I don't get it. How is ((.) (+) ((*) a)) b c = ((.) (+) . (*)) a b c? What is f and g here if this were perceived as (f . g) x = f (g x)?
    – TobiMcNamobi
    Nov 2 at 14:08






  • 1




    @TobiMcNamobi f = (.) (+) = ((.) (+)) ; g = (*) ; (f (g a)) == (f . g) a. b, c are just hanging, irrelevant for this transformation. extraneous parentheses are also irrelevant.
    – Will Ness
    Nov 2 at 14:14












  • @WillNess thanks for the thorough explanation previously. So based on it, I've worked on another example i attempted in the updated post above, would appreciate if you could assess it and inform me if I'm right with the rules.
    – jazzer97
    Nov 4 at 8:25










  • you're welcome. I'll edit the answer shortly.
    – Will Ness
    Nov 4 at 9:51










  • @WillNess thank you. One question, why is it that its div a (g b) then reverted back to (a div) (g b)? Does the ` ` play a role in the change?
    – jazzer97
    Nov 4 at 10:54


















  • Sorry, I don't get it. How is ((.) (+) ((*) a)) b c = ((.) (+) . (*)) a b c? What is f and g here if this were perceived as (f . g) x = f (g x)?
    – TobiMcNamobi
    Nov 2 at 14:08






  • 1




    @TobiMcNamobi f = (.) (+) = ((.) (+)) ; g = (*) ; (f (g a)) == (f . g) a. b, c are just hanging, irrelevant for this transformation. extraneous parentheses are also irrelevant.
    – Will Ness
    Nov 2 at 14:14












  • @WillNess thanks for the thorough explanation previously. So based on it, I've worked on another example i attempted in the updated post above, would appreciate if you could assess it and inform me if I'm right with the rules.
    – jazzer97
    Nov 4 at 8:25










  • you're welcome. I'll edit the answer shortly.
    – Will Ness
    Nov 4 at 9:51










  • @WillNess thank you. One question, why is it that its div a (g b) then reverted back to (a div) (g b)? Does the ` ` play a role in the change?
    – jazzer97
    Nov 4 at 10:54
















Sorry, I don't get it. How is ((.) (+) ((*) a)) b c = ((.) (+) . (*)) a b c? What is f and g here if this were perceived as (f . g) x = f (g x)?
– TobiMcNamobi
Nov 2 at 14:08




Sorry, I don't get it. How is ((.) (+) ((*) a)) b c = ((.) (+) . (*)) a b c? What is f and g here if this were perceived as (f . g) x = f (g x)?
– TobiMcNamobi
Nov 2 at 14:08




1




1




@TobiMcNamobi f = (.) (+) = ((.) (+)) ; g = (*) ; (f (g a)) == (f . g) a. b, c are just hanging, irrelevant for this transformation. extraneous parentheses are also irrelevant.
– Will Ness
Nov 2 at 14:14






@TobiMcNamobi f = (.) (+) = ((.) (+)) ; g = (*) ; (f (g a)) == (f . g) a. b, c are just hanging, irrelevant for this transformation. extraneous parentheses are also irrelevant.
– Will Ness
Nov 2 at 14:14














@WillNess thanks for the thorough explanation previously. So based on it, I've worked on another example i attempted in the updated post above, would appreciate if you could assess it and inform me if I'm right with the rules.
– jazzer97
Nov 4 at 8:25




@WillNess thanks for the thorough explanation previously. So based on it, I've worked on another example i attempted in the updated post above, would appreciate if you could assess it and inform me if I'm right with the rules.
– jazzer97
Nov 4 at 8:25












you're welcome. I'll edit the answer shortly.
– Will Ness
Nov 4 at 9:51




you're welcome. I'll edit the answer shortly.
– Will Ness
Nov 4 at 9:51












@WillNess thank you. One question, why is it that its div a (g b) then reverted back to (a div) (g b)? Does the ` ` play a role in the change?
– jazzer97
Nov 4 at 10:54




@WillNess thank you. One question, why is it that its div a (g b) then reverted back to (a div) (g b)? Does the ` ` play a role in the change?
– jazzer97
Nov 4 at 10:54












up vote
3
down vote













We can continue with:



function2 a b = (+) ((*) a b)     [eta-reduction]
function2 a = (+) . (*) a [using a dot, to eliminate the b]
function2 = ((.) . (.)) (+) (*) ["blackbird" operator to pass two parameters]


Here the "blackbird operator" is a combination of three (.) :: (b -> c) -> (a -> b) -> a -> c operators. It is functionally equivalent to:



((.) . (.)) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
((.) . (.)) f g x y = f (g x y)


see here for a derivation.






share|improve this answer























  • I presume you’re calling it “owl” to avoid the fact that people in practice refer to it as a different kind of hooters, but in the usual aviary of combinator birds, the owl O is λfg.g(fg); this is the blackbird B₁ = λfgxy.f(gxy), sometimes spelled (.:), (...), or fmap fmap fmap if you want to be silly about it. For my pointfree code though, I prefer to just add an fmapfmap (+) . (*)—since even though it’s just composition here, semantically I think of it as “mapping over” the extra argument.
    – Jon Purdy
    Nov 2 at 19:10















up vote
3
down vote













We can continue with:



function2 a b = (+) ((*) a b)     [eta-reduction]
function2 a = (+) . (*) a [using a dot, to eliminate the b]
function2 = ((.) . (.)) (+) (*) ["blackbird" operator to pass two parameters]


Here the "blackbird operator" is a combination of three (.) :: (b -> c) -> (a -> b) -> a -> c operators. It is functionally equivalent to:



((.) . (.)) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
((.) . (.)) f g x y = f (g x y)


see here for a derivation.






share|improve this answer























  • I presume you’re calling it “owl” to avoid the fact that people in practice refer to it as a different kind of hooters, but in the usual aviary of combinator birds, the owl O is λfg.g(fg); this is the blackbird B₁ = λfgxy.f(gxy), sometimes spelled (.:), (...), or fmap fmap fmap if you want to be silly about it. For my pointfree code though, I prefer to just add an fmapfmap (+) . (*)—since even though it’s just composition here, semantically I think of it as “mapping over” the extra argument.
    – Jon Purdy
    Nov 2 at 19:10













up vote
3
down vote










up vote
3
down vote









We can continue with:



function2 a b = (+) ((*) a b)     [eta-reduction]
function2 a = (+) . (*) a [using a dot, to eliminate the b]
function2 = ((.) . (.)) (+) (*) ["blackbird" operator to pass two parameters]


Here the "blackbird operator" is a combination of three (.) :: (b -> c) -> (a -> b) -> a -> c operators. It is functionally equivalent to:



((.) . (.)) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
((.) . (.)) f g x y = f (g x y)


see here for a derivation.






share|improve this answer














We can continue with:



function2 a b = (+) ((*) a b)     [eta-reduction]
function2 a = (+) . (*) a [using a dot, to eliminate the b]
function2 = ((.) . (.)) (+) (*) ["blackbird" operator to pass two parameters]


Here the "blackbird operator" is a combination of three (.) :: (b -> c) -> (a -> b) -> a -> c operators. It is functionally equivalent to:



((.) . (.)) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
((.) . (.)) f g x y = f (g x y)


see here for a derivation.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 2 at 20:25

























answered Nov 2 at 10:05









Willem Van Onsem

137k16129219




137k16129219












  • I presume you’re calling it “owl” to avoid the fact that people in practice refer to it as a different kind of hooters, but in the usual aviary of combinator birds, the owl O is λfg.g(fg); this is the blackbird B₁ = λfgxy.f(gxy), sometimes spelled (.:), (...), or fmap fmap fmap if you want to be silly about it. For my pointfree code though, I prefer to just add an fmapfmap (+) . (*)—since even though it’s just composition here, semantically I think of it as “mapping over” the extra argument.
    – Jon Purdy
    Nov 2 at 19:10


















  • I presume you’re calling it “owl” to avoid the fact that people in practice refer to it as a different kind of hooters, but in the usual aviary of combinator birds, the owl O is λfg.g(fg); this is the blackbird B₁ = λfgxy.f(gxy), sometimes spelled (.:), (...), or fmap fmap fmap if you want to be silly about it. For my pointfree code though, I prefer to just add an fmapfmap (+) . (*)—since even though it’s just composition here, semantically I think of it as “mapping over” the extra argument.
    – Jon Purdy
    Nov 2 at 19:10
















I presume you’re calling it “owl” to avoid the fact that people in practice refer to it as a different kind of hooters, but in the usual aviary of combinator birds, the owl O is λfg.g(fg); this is the blackbird B₁ = λfgxy.f(gxy), sometimes spelled (.:), (...), or fmap fmap fmap if you want to be silly about it. For my pointfree code though, I prefer to just add an fmapfmap (+) . (*)—since even though it’s just composition here, semantically I think of it as “mapping over” the extra argument.
– Jon Purdy
Nov 2 at 19:10




I presume you’re calling it “owl” to avoid the fact that people in practice refer to it as a different kind of hooters, but in the usual aviary of combinator birds, the owl O is λfg.g(fg); this is the blackbird B₁ = λfgxy.f(gxy), sometimes spelled (.:), (...), or fmap fmap fmap if you want to be silly about it. For my pointfree code though, I prefer to just add an fmapfmap (+) . (*)—since even though it’s just composition here, semantically I think of it as “mapping over” the extra argument.
– Jon Purdy
Nov 2 at 19:10


















 

draft saved


draft discarded



















































 


draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53116154%2ftransforming-a-function-in-haskell-to-point-free-notation%23new-answer', 'question_page');
}
);

Post as a guest




















































































這個網誌中的熱門文章

Xamarin.form Move up view when keyboard appear

Post-Redirect-Get with Spring WebFlux and Thymeleaf

Anylogic : not able to use stopDelay()