3

In F#, is there a way to treat an operator as a function? In context, I'd like to partially apply operators (both infix and prefix), but the compiler only seems happy to partially apply functions.

Example: Instead of being able to write List.map (2 **) [0..7];; I have to define my own function pow x y (and then another function let swap f x y = f y x;; because the compiler won't let me partially apply |> either, as in List.map (|> pow 2) [0..7];;.) In the end, my code needs to be List.map (swap pow 2) [0..7];; to work.

2 Answers 2

5

I would just do:

[0..7] |> List.map (fun n -> pown n 2)

Or, if 2 is the base:

[0..7] |> List.map (pown 2)

This works too:

[0.0..7.0] |> List.map (( ** ) 2.0)
Sign up to request clarification or add additional context in comments.

7 Comments

The lambda works, and if rewritten like this then I'm not forced to go searching for an efficient algorithm of [insert_operator_name_here]. [0.0..7.0] |> List.map (fun y -> 2.0 ** y);;
The other option still forces me to define ** as a function though.
Thanks Daniel. After squinting at your 3rd example I discovered it's actually the whitespace that's been catching me out and I can, in fact, invoke List.map (( |> ) 2.0 ( ** )) [0.0..7.0];;
@Jono - While you can certainly write (( |> ) 2.0 ( ** )) as an argument of List.map, I honestly think that this is a really bad idea. It has exactly the same number of characters as (fun a -> a ** 2.0) and it takes much longer to decipher what is actually going on. The thrid example from Daniel is pretty common, so I think that's fine, but anything beyond that is often too complicated. (Although this is just my personal preference and anybody can disagree with it.)
(( |> ) 2.0 ( ** )) can be made look as ( 2.0 |> ( ** ))
|
3

There are no 'operator sections' a la Haskell; use a lambda to partially apply operators, e.g.

(fun x -> x - 10)

You can partially apply the first argument if you make an infix operator be prefix by surrounding it in parens, e.g.

(fun x -> 10.0 / x)

and

((/) 10.0)

mean the same thing.

2 Comments

Thanks, Brian. Any ideas why (/) doesn't need spaces, but ( ** ) does, even though both operators are infix?
@Jono - becaus (* opens a comment and *) closes a comment. So (**) is just whitespace.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.