“Situations often arise where I need to curry the second argument of a function. For example, the divisor in (/). It’s not hard to come up with a function or operator for doing this, as the following code illustrates. But is there a way to do it in F# without defining a new function or operator?”

For instance, one might want to curry the second argument of the divide function (/) in order to produce a curried “divide-by-N” function. This kind of operation is very common in stack-based languages like FORTH, but is not usually needed in imperative languages.

Here is some code that illustrates what I want to do. I decided to use “><” to represent the “flip*” or “swap” operator.

`// This code is presented "as-is" and without warranty `

`// or implied fitness of any kind; use at your own risk. `

`// "Flip" or "swap" operations:`

let flip f a b = f b a

let (><) f a b = f b a

`// Sundry tests:`

let thisIs20 = ((/) >< 5) 100

let also20 = ((><) (/) 5) 100

let d5'0 = flip (/) 5

let d5'1 = (/) >< 5

let m5'0 = flip (%) 5

let m5'1 = (%) >< 5

let t0 = d5'0 99 // 19

let t1 = d5'1 99 // 19

let t2 = m5'0 99 // 4

let t3 = m5'1 99 // 4

let divBy = (><) (/)

let divBy5 = divBy 5

let shouldBe20 = divBy5 100

`// etc.`

I ask again: is there a good native way to do this in F#? If not, it might well worth standardizing this. (And potentially other FORTH-like operators like “over” and “rot,” perhaps with an extensible syntax.)

-Neil

*Name suggested by “mau” on hubFS.

## 4 comments:

True, 'flip' is standard in the Haskell prelude. Strange that it's missing in F#. That and 'curry'/'uncurry'... Useful for point-free style, which I personally love

Thanks for the comment, Ashley. To steal a phrase from the Lord of the Rings: "Even the smallest operator can change the course of the future."

By the way, as someone who was first introduced to functional programming via LISP/Scheme, I really appreciate your FScheme series!

This is neat, one of my annoyances is when trying to simplify (for example) filter operations, eg:

[1..100] |> List.filter ((>)50)

Which counterintuitively returns all values which are less than 50, and the 50 applies to the other side of (>). So if I do:

[1.100] |> List.filter ((flip(>))50)

I get the intuitive result of all values greater than 50. Nice - thanks Neil.

Thank you, Chris! One of my favorite things about F# is the way even small changes to operators (etc.) can make a real improvement in the readability of code. That is, they can make the code "look like what it does." I think it's maintenance factors like this that are helping to drive the acceptance of F#.

Post a Comment