2

I want to write List.map (fun x -> x % 3) into a form like List.map ((%) 3).
The issue with the latter is that it translates to
List.map (fun x -> 3 % x) Not what I want.

Is it possible to write List.map (fun x -> x % 3). in a more succinct fashion?

Further context
New to F#. Find it nice to be able to write succinct expressions with partial applications.

E.g. for the logic add 3 to each item in list can be written just as List.map ((+) 3).

However, this doesn't apply to positional sensitive ops like division and modulus.
E.g. I read List.map ((/) 3) as - for each item in list, divide by 3.
But the actual logic is actually mapping 3 divided each item.

[12; 24; 36; 48] |> List.map ((/) 3)
// expect [4; 8; 12; 16]
// actual [3/12; 3/24; 3/36; 3/48] // type discrepancy. but just an example.

From JL0PD's answer, I think what I want is not possible with F# (at the moment).


Retrospect

What I want is not feasible due to the nature of currying/parameter positioning. E.g.
(/) 12 3 = 12 / 3  // left hand op and right hand op are equivalent.
// val it: bool = true
SAm
  • 2,154
  • 28
  • 28
  • 1
    Interesting example of using lenses. Maybe it will allow do what you want https://www.haskellforall.com/2013/05/program-imperatively-using-haskell.html?m=1 – JL0PD Apr 18 '22 at 12:06
  • @JLOPD's answer is the best way and is long used both formally in Haskell and, informally, inf F# since you have to define `flip` yourself. There wont be anything else in the future. An outstanding question is as to why `flip` is not a formal part of the language. – Martin Freedman Apr 18 '22 at 13:31
  • @MartinFreedman, Don Syme, author of F#, several times gave talk `F# code I love`. He explains many decision behind language design. As another source of "why", there's [history of F#](https://fsharp.org/history/), 58 pages of reflection on F# history, impact and design – JL0PD Apr 18 '22 at 13:50
  • Yup I am familiar with all that. It is just a pain to add `flip` to nearly f# project. I do agree with most of his reasoning over `<|` and not having `>|` and `<|` in one line, but `flip` solves that. – Martin Freedman Apr 18 '22 at 13:54

2 Answers2

4

Common workaround for functions that have incorrect order of parameters is flip function

let flip f x y = f y x

With this function you can write

List.map (flip (%) 3)

A bit less universal, but more clear is to create specialized function, like mod

let mod y x = x % y
List.map (mod 3)

But I don't think that that's increases readability and/or maintainability. I would use current version instead

JL0PD
  • 3,698
  • 2
  • 15
  • 23
  • I would not say it is an _incorrect_ order of arguments, just not the desired order for the case at hand. This is a common issue in functional programming hence the need for a function to reverse arguments. – Martin Freedman Apr 18 '22 at 14:00
1

I fully agree with JL0PD' answer . One more alternative is that you can define your own operator. i.e.

let (%.) x y = y % x 
[12; 24; 36; 48] |> List.map ((%.) 3)
pjaras
  • 11
  • 1