Custom prefix operators in F# once again - f#

No matter how many times I read this post: F#: What are the valid prefix operators?
Me and the F# compiler never agrees on what are custom prefix (or infix) operator names.
In the above post it says that "+" can be both an infix and prefix operator, but this:
let (+#) a = a + 20
+# 30 |> printfn "%d"
gives the error "Invalid prefix operator".
Why?

If you'll look through Brian's answer in the link you provided you'll find that operator +# is not listed among prefix-op. And to be used as prefix operator, the operator + should be prepended by ~:
let (~+) a = a + 20
+ 30 |> printfn "%d"
Result:
50

Related

How to use F# exponentiation operator (**) in prefix notation?

With most operators in F# I can use prefix or infix notation, for example:
let x = a + b
is equivalent to
let x = (+) a b
This does not work for the exponentation operator ** however, because the parenthesised version is treated as a comment. That is, (*this is a comment*) is F# syntax for a comment, so (**) is treated as an empty comment.
let x = a ** b // a raised to b
let x = (**) a b // empty comment, followed by function a applied to b
Is there an escape character I can use or is this simply a strange quirk of the language?
Try using spaces between the parentheses, as pointed by kvb in the comments:
let x = ( ** ) a b

Why is this (~=) considered a prefix operator?

let tolerance = 0.00000001
let (~=) x1 x2 = abs(x1 - x2) < tolerance
This throws the error:
"invalid operator definition. Prefix operator definitions must use a valid prefix operator name"
This isn't even a prefix operator, I don't get why it thinks so.
However the following is fine:
let (=~) x1 x2 = abs(x1 - x2) < tolerance
I only switched the order, so "=" comes before "~".
Is there any document online stating some rules regarding this?
I'm using Visual Studio 2013 with "F# 2013". The interactive console says "F# Interactive version 12.0.21005.1"
You can't define an infix operator starting with ~ in F#.
The F# 3.0 specification, section Categorization of Symbolic Operators explains the reason quite clearly:
The operators +, -, +., -., %, %%, &, && can be used as both prefix and infix operators. When these operators are used as prefix operators, the tilde character is prepended internally to generate the operator name so that the parser can distinguish such usage from an infix use of the operator. For example, -x is parsed as an application of the operator ~- to the identifier x. This generated name is also used in definitions for these prefix operators. Consequently, the definitions of the following prefix operators include the ~ character.
In F#, the ~ character in first position denotes a prefix operator. For example, (~-) is the prefix "opposite" operator: (~-) 3 is equivalent to - 3.

How to write an infix function

Is there a way to write an infix function not using symbols? Something like this:
let mod x y = x % y
x mod y
Maybe a keyword before "mod" or something.
The existing answer is correct - you cannot define an infix function in F# (just a custom infix operator). Aside from the trick with pipe operators, you can also use extension members:
// Define an extension member 'modulo' that
// can be called on any Int32 value
type System.Int32 with
member x.modulo n = x % n
// To use it, you can write something like this:
10 .modulo 3
Note that the space before . is needed, because otherwise the compiler tries to interpret 10.m as a numeric literal (like 10.0f).
I find this a bit more elegant than using pipeline trick, because F# supports both functional style and object-oriented style and extension methods are - in some sense - close equivalent to implicit operators from functional style. The pipeline trick looks like a slight misuse of the operators (and it may look confusing at first - perhaps more confusing than a method invocation).
That said, I have seen people using other operators instead of pipeline - perhaps the most interesting version is this one (which also uses the fact that you can omit spaces around operators):
// Define custom operators to make the syntax prettier
let (</) a b = a |> b
let (/>) a b = a <| b
let modulo a b = a % b
// Then you can turn any function into infix using:
10 </modulo/> 3
But even this is not really an established idiom in the F# world, so I would probably still prefer extension members.
Not that I know of, but you can use the left and right pipe operators. For example
let modulo x y = x % y
let FourMod3 = 4 |> modulo <| 3
To add a little bit to the answers above, you can create a custom infix operators but the vocabulary is limited to:
!, $, %, &, *, +, -, ., /, <, =, >, ?, #, ^, |, and ~
Meaning you can build your infix operator using combining these symbols.
Please check the full documentation on MS Docs.
https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/operator-overloading

Strange expression parsing behavior

In this code:
let f(a,b,c) = a * b + c - (d())
let g(a,b,c) = a * b + c -(d())
f is (int*int*int) -> int, and g is (int*int*(int*int)) -> int.
Removing the brackets around d() in g causes the "Successive arguments should be separated by spaces or tupled" error.
What's going on?
#bytebuster is quite correct in his comment, but to put it into layman's terms ;-] one is parsed as the binary subtraction operator and the other is parsed as the unary negation operator – you're simply fighting operator precedence here.

Is there any built-in function for human-readable F# quotations?

When quoting
<# 1 + 1 #>
I want "1 + 1"
instead of
"Call (None, Int32 op_Addition[Int32,Int32,Int32](Int32, Int32),
[Value (1), Value (1)])"
You'll have to write it yourself. See the F# quotations visualizer code as a guide for transforming the quotations abstract syntax tree.
I have implemented a quotation decompiler as part of a larger open source project Unquote. It can decompile many simple F# quoted expressions as single-line non-light syntax strings (see the project's home page for a list of decompiler features). For example,
> decompile <# (11 + 3) / 2 = String.length ("hello world".Substring(4, 5)) #>;;
val it : string =
"(11 + 3) / 2 = String.length ("hello world".Substring(4, 5))"
#Kurt Schelfthout is correct about the many challenges faced when decompiling F# Quotations into human readable form. But from my work so far, I believe that it is possible to write a quotation decompiler which can generate correct F# code. Take match expressions and computation expressions for example, the Unquote decompiler can produce correct F# code in the following simple cases:
> decompile <# match true with | true -> "hi" | _ -> "bye" #>;;
val it : string =
"let matchValue = true in if matchValue then "hi" else "bye""
> decompile <# seq {yield 1; yield 2} #>;;
val it : string =
"seq (Seq.delay (fun unitVar -> Seq.append (Seq.singleton 1) (Seq.delay (fun unitVar -> Seq.singleton 2))))"
Infix and prefix operators are not too hard (as you can see in the first example), but source structure such as new lines and indentation is an interesting topic (though not terribly difficult, I think). However, single-line non-light syntax is sufficient for Unquote's requirements.
There is none, and it's not quite that easy, except in very simple cases. One of the main problems, for example, is the match construct. It is syntactic sugar for a whole bunch of if and switch statements (try printing a quotation with a match in, you'll see). Another one of those biggies are computation expressions, but I guess you could skip those at first.
Then there is a the rabbit hole of ambiguities you'll have to resolve, with conventions like the pipe operator starts a new line, let starts a new line, indentation, infix, prefix, special cases like the (::) operator and so forth.
All in all, doable, but not trivial. Sort of like decompiling.

Resources