0

This is a useless case of concatenation via foldl, purely educational (for me):

foldl (\xs x -> xs ++ [x]) [1,2] [11,12,13]
[1,2,11,12,13]

Is there a way to pack it even tighter, using composition instead of the lambda?

Alexey Orlov
  • 2,412
  • 3
  • 27
  • 46
  • 1
    `foldl ((. return) . (++))`. But it is better to use `flip (foldr (:))`. – Willem Van Onsem Dec 20 '17 at 14:36
  • Thanks! That much abour `foldr` I already figured out :) . I've been just grokking. – Alexey Orlov Dec 20 '17 at 14:41
  • 1
    If you care about performance, know that `foldl` is quite inefficient, in general. `foldl'` is better, but it should only be used when the resulting type is small (e.g. a single `Int`). `foldr` is also OK, provided that the folding function is non-strict. – chi Dec 20 '17 at 14:45
  • @WillemVanOnsem If we are going to use `(++)` anyway, we can replace `foldl (\xs x -> ...)` with `(++)`, avoiding the folds. – chi Dec 20 '17 at 14:47
  • Thanks, but no, I don't care for efficiency. It's just doodles, I'm studying. – Alexey Orlov Dec 20 '17 at 14:51
  • @WillemVanOnsem Would you mind expounding a bit on this particular kind of composition? – Alexey Orlov Dec 20 '17 at 14:55
  • You can [mechanically reduce](http://pointfree.io) any lambda expression to make it into pure composition. This usually involves `(.)`, `flip` to manage argument order, and `const` and `(<*>)` to ignore/duplicate arguments, respectively. It might help to add points to the function and simplify if you want to see how it works: `\hd tl -> ((. return) . (++)) hd tl = \hd tl -> ((. return) (hd ++)) tl = \hd tl -> ((hd ++) . return) tl = \hd tl -> hd ++ return tl = \hd tl -> hd ++ [tl]`. Forms like `(. x) . y` and `(x .) . y` compose functions with different numbers of arguments. – HTNW Dec 20 '17 at 16:19
  • Kinda magnificent. I'll have to think a bit. – Alexey Orlov Dec 20 '17 at 16:39
  • Somehow can't figure out the entity meant between the dot and the parenthesis. Must be another function, of course, but... – Alexey Orlov Dec 20 '17 at 16:55
  • `(. x)` is an [operator section](https://stackoverflow.com/a/13147064/849891): a [partially applied operator](https://stackoverflow.com/a/37979558/849891), here `(.)`: `(. x) y = (y . x) = (y .) x = (.) y x`, by definition. it's just *syntax*. And `(. x) y z = (y . x) z = y (x z)`. Similarly, `((. x) . y) z w = (. x) (y z) w = ((y z) . x) w = (y z) (x w) = y z (x w)`. The manipulations of the equations are purely syntactical. – Will Ness Dec 20 '17 at 21:37
  • also, `(. x) y = (y . x) = (.) y x = flip (.) x y`, *hence* `(. x) = flip (.)` by *"eta contraction"*. Similarly `(y .) = (.) y`. --- and, what you're asking about is known as *[tag:pointfree] programming*. – Will Ness Dec 20 '17 at 21:44
  • Thank you very much! It amounts to exhaustive answer. BTW, is there a way to partially apply to arguments not starting with the first one? Only third and fourth to a function of five args, for instance? Operator section rules suggest such possibility. Or is it just `flip` over two arguments? And how am I supposed to declare this post answered? – Alexey Orlov Dec 21 '17 at 02:52

1 Answers1

1

This is just a better readable summary extracted from the comments by HTNW and Will Ness:

-- Reduction to poinfree
a = \xs x -> xs ++ [x]
b = \xs x -> xs ++ return x
c = \xs x -> ((xs ++) . return) x
d = \xs x -> ((. return) (xs ++)) x
e = \xs x -> ((. return) . (++)) xs x
Alexey Orlov
  • 2,412
  • 3
  • 27
  • 46