post04-curried-functions.skr 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. (post
  2. :title "Curried functions and the beauty of scheme's cut"
  3. :date (make-date* 2016 9 26)
  4. :tags '("guile" "scheme" "curry" "curried" "haskell" "cut")
  5. (h3 [Curried functions in Haskell])
  6. (p [
  7. If you weren't aware, functions in languages like ML and Haskell are
  8. curried, meaning each function technically only accepts
  9. one parameter.
  10. Mathematically, curried functions help programmers reason
  11. about runtimes since each function only has one parameter.
  12. Programatically, however, their use is not immediately apparent. Both
  13. Haskell and ML allow the programmer to declare functions with multiple
  14. parameters, which are then curried under the hood. Now I'm sure
  15. experienced Haskellers are shaking their head, and could explain all the
  16. programmatic features currying provides, but for my inexperienced self,
  17. I enjoyed the ease in building partially ordered functions.
  18. ])
  19. (h3 [Example])
  20. (p [
  21. To make this clear let's look at common map subroutine, where we
  22. increment each element in a list, in lisp and
  23. haskell. Since (+ 1) in lisp returns 1, we have to nest this
  24. procedure in a lambda specifying + will take two arguments:
  25. ])
  26. (code-block-scheme
  27. (car
  28. [(map (lambda (x) (+ 1 x))
  29. '(1 2 3))]))
  30. (p [
  31. In haskell, however, (+ 1) returns an increment function of one
  32. argument, exactly what the lisp boilerplate does. It looks like:
  33. ])
  34. (code-block-scheme
  35. (car
  36. [(map (+ 1) '(1 2 3))]))
  37. (p [
  38. There are some limitations when using curried functions in this manner.
  39. In particular, commutivity is required: (+ 1 _) works but (- _ 1) does not.
  40. ])
  41. (h3 [Lisp's cut])
  42. (p [
  43. Eventually I found about cut, an awesome lisp macro that implements
  44. the nice feature currying provides, without the limitations. Cut
  45. essentially allows the programmer to specify which procedure arguments
  46. will be supplied later, and returns a new procedure with those rules.
  47. So for the above example, we would use cut like this:
  48. ])
  49. (code-block-scheme
  50. (car
  51. [(map (cut + 1 <>) '(1 2 3))]))
  52. (p [
  53. As you may have noted, <> can be anywhere, which means that we can deal
  54. with non-communitive operators: (cut - <> 1), multiple arugments:
  55. (cut - <> <>), an arbitrary number of arugments: (cut - <...>) even
  56. the procedure itself: (cut <> 1 1)
  57. ]))