Transforming a function in Haskell to point free notation
up vote
5
down vote
favorite
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
add a comment |
up vote
5
down vote
favorite
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
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
add a comment |
up vote
5
down vote
favorite
up vote
5
down vote
favorite
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
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
haskell pointfree
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
add a comment |
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
add a comment |
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.
Sorry, I don't get it. How is((.) (+) ((*) a)) b c = ((.) (+) . (*)) a b c
? What isf
andg
here if this were perceived as(f . g) x = f (g x)
?
– TobiMcNamobi
Nov 2 at 14:08
1
@TobiMcNamobif = (.) (+) = ((.) (+)) ; 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 (adiv
) (g b)? Does the ` ` play a role in the change?
– jazzer97
Nov 4 at 10:54
|
show 1 more comment
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.
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(.:)
,(...)
, orfmap fmap fmap
if you want to be silly about it. For my pointfree code though, I prefer to just add anfmap
—fmap (+) . (*)
—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
add a comment |
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.
Sorry, I don't get it. How is((.) (+) ((*) a)) b c = ((.) (+) . (*)) a b c
? What isf
andg
here if this were perceived as(f . g) x = f (g x)
?
– TobiMcNamobi
Nov 2 at 14:08
1
@TobiMcNamobif = (.) (+) = ((.) (+)) ; 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 (adiv
) (g b)? Does the ` ` play a role in the change?
– jazzer97
Nov 4 at 10:54
|
show 1 more comment
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.
Sorry, I don't get it. How is((.) (+) ((*) a)) b c = ((.) (+) . (*)) a b c
? What isf
andg
here if this were perceived as(f . g) x = f (g x)
?
– TobiMcNamobi
Nov 2 at 14:08
1
@TobiMcNamobif = (.) (+) = ((.) (+)) ; 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 (adiv
) (g b)? Does the ` ` play a role in the change?
– jazzer97
Nov 4 at 10:54
|
show 1 more comment
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.
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.
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 isf
andg
here if this were perceived as(f . g) x = f (g x)
?
– TobiMcNamobi
Nov 2 at 14:08
1
@TobiMcNamobif = (.) (+) = ((.) (+)) ; 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 (adiv
) (g b)? Does the ` ` play a role in the change?
– jazzer97
Nov 4 at 10:54
|
show 1 more comment
Sorry, I don't get it. How is((.) (+) ((*) a)) b c = ((.) (+) . (*)) a b c
? What isf
andg
here if this were perceived as(f . g) x = f (g x)
?
– TobiMcNamobi
Nov 2 at 14:08
1
@TobiMcNamobif = (.) (+) = ((.) (+)) ; 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 (adiv
) (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
|
show 1 more comment
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.
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(.:)
,(...)
, orfmap fmap fmap
if you want to be silly about it. For my pointfree code though, I prefer to just add anfmap
—fmap (+) . (*)
—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
add a comment |
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.
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(.:)
,(...)
, orfmap fmap fmap
if you want to be silly about it. For my pointfree code though, I prefer to just add anfmap
—fmap (+) . (*)
—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
add a comment |
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.
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.
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(.:)
,(...)
, orfmap fmap fmap
if you want to be silly about it. For my pointfree code though, I prefer to just add anfmap
—fmap (+) . (*)
—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
add a comment |
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(.:)
,(...)
, orfmap fmap fmap
if you want to be silly about it. For my pointfree code though, I prefer to just add anfmap
—fmap (+) . (*)
—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 fmap
—fmap (+) . (*)
—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 fmap
—fmap (+) . (*)
—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
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
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
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
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
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
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