Stumbled upon this question in the related questions list of How to golf a fork in Haskell?. Now that I have a better understanding of combinator golf, I gave it a try.
Primer: Haskell supports a few combinators including the standard S, B, C, K, I:
-- I
id = \x -> x
-- K
pure = \x y -> x -- 1 byte shorter than `const`
-- S
(<*>) = \x y z -> x z (y z)
-- B
(.) = \x y z -> x (y z)
-- C
flip = \x y z -> x z y
-- Variations of S
(>>=) = \x y z -> y (x z) z
(=<<) = \x y z -> x (y z) z
liftA2 = \f g h x -> f (g x) (h x) -- part of latest Prelude
Now, there are two possible forms to convert to pointfree:
v1 :: (b -> b -> c) -> (a -> b) -> (a -> a -> c)
v1 f g x y = f (g x) (g y)
v2 :: (a -> b) -> (b -> b -> c) -> (a -> a -> c)
v2 f g x y = g (f x) (f y)
The following are all the various reductions I tried (along with typechecking):
import Control.Applicative
type On a b c = (b -> b -> c) -> (a -> b) -> a -> a -> c
fref :: On a b c
fref g h x y=g(h x)(h y)
f1 :: On a b c
f1=(flip flip<*>).(.).((.).)
f2 :: On a b c
f2 z g=(.g).z.g
f3 :: On a b c
f3=(flip=<<).(.).((.).)
f4 :: On a b c
f4=liftA2(.)(flip(.)).(.)
f5 :: On a b c
f5=((.).(flip(.))<*>).(.)
type On2 a b c = (a -> b) -> (b -> b -> c) -> a -> a -> c
fref' :: On2 a b c
fref' g h x y=h(g x)(g y)
f1' :: On2 a b c
f1' g=((.g).).(.g)
f2' :: On2 a b c
f2'=liftA2(.)((.).flip(.))(flip(.))
f3' :: On2 a b c
f3' g z=(.g).z.g
f4' :: On2 a b c
f4'=(.).(.).flip(.)<*>flip(.)
f5' :: On2 a b c
f5'=(.).(.).q<*>q;q=flip(.)
f6' :: On2 a b c
f6' g=(.g).((.g).)
f7' :: On2 a b c
f7'=r<*>r;r=(.).flip(.)
f8' :: On2 a b c
f8'=s<*>s;s x=(.)(.x)
Try it online!
Unfortunately, the shortest unnamed lambda version is the same as OP's of
\z g->(.g).z.g
at 14 bytes, supporting both versions (just swap g
and z
in the argument list for the alternative version).
The shortest pointfree solution I could find was
(flip=<<).(.).((.).)
at 20 bytes (which has the type of v1
), which is 5 bytes shorter than OP's. For v2
, I got two different 25 byters.
The reduction steps to reach this one:
\f g a b -> f (g a) (g b)
\f g a -> B (f (g a)) g
\f g -> C (\a -> B (f (g a))) g
\f g -> C (B (B B f) g) g
\f g -> (=<<) C (B (B B f)) g
\f -> (=<<) C (B (B B f))
((=<<)C).B.BB
(flip=<<).(.).((.).)
on
but you need toimport Data.Function
. \$\endgroup\$