1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768 |
- (post
- :title "Curried functions and the beauty of scheme's cut"
- :date (make-date* 2016 9 26)
- :tags '("guile" "scheme" "curry" "curried" "haskell" "cut")
- (h3 [Curried functions in Haskell])
- (p [
- If you weren't aware, functions in languages like ML and Haskell are
- curried, meaning each function technically only accepts
- one parameter.
- Mathematically, curried functions help programmers reason
- about runtimes since each function only has one parameter.
- Programatically, however, their use is not immediately apparent. Both
- Haskell and ML allow the programmer to declare functions with multiple
- parameters, which are then curried under the hood. Now I'm sure
- experienced Haskellers are shaking their head, and could explain all the
- programmatic features currying provides, but for my inexperienced self,
- I enjoyed the ease in building partially ordered functions.
- ])
- (h3 [Example])
- (p [
- To make this clear let's look at common map subroutine, where we
- increment each element in a list, in lisp and
- haskell. Since (+ 1) in lisp returns 1, we have to nest this
- procedure in a lambda specifying + will take two arguments:
- ])
- (code-block-scheme
- (car
- [(map (lambda (x) (+ 1 x))
- '(1 2 3))]))
- (p [
- In haskell, however, (+ 1) returns an increment function of one
- argument, exactly what the lisp boilerplate does. It looks like:
- ])
-
- (code-block-scheme
- (car
- [(map (+ 1) '(1 2 3))]))
- (p [
- There are some limitations when using curried functions in this manner.
- In particular, commutivity is required: (+ 1 _) works but (- _ 1) does not.
- ])
- (h3 [Lisp's cut])
- (p [
- Eventually I found about cut, an awesome lisp macro that implements
- the nice feature currying provides, without the limitations. Cut
- essentially allows the programmer to specify which procedure arguments
- will be supplied later, and returns a new procedure with those rules.
- So for the above example, we would use cut like this:
- ])
- (code-block-scheme
- (car
- [(map (cut + 1 <>) '(1 2 3))]))
- (p [
- As you may have noted, <> can be anywhere, which means that we can deal
- with non-communitive operators: (cut - <> 1), multiple arugments:
- (cut - <> <>), an arbitrary number of arugments: (cut - <...>) even
- the procedure itself: (cut <> 1 1)
- ]))
|