This code doesn't compile:
let f (x:byte) = printfn "%d" x
let b = int 'a'
f(byte <| b ||| 0x1)
(4,17): error FS0001: This expression was expected to have type
byte
but here has type
int
http://ideone.com/C6KoCQ
The F# operator table states the backward pipe operaotor (<|) which has a form of (< op) has a lower precedence than the bitwise or operator (|||):
http://msdn.microsoft.com/en-us/library/dd233228.aspx
So I thought (byte <| b ||| 0x1) should be parsed as (byte <| (b ||| 0x1)). But the compiler error message suggests it is parsed as ((byte <| b) ||| 0x1). What's happening here?
I just had a look at the FSharp specs and there <| indeed has higher precedence than ||| (if I read the table right)
So most likely it's either an error in the MSDN docs or it was changed and not updated.
It's on page 35:
Related
I am learning F# and the use cases of the |>, >>, and << operators confuse me. I get that everything if statements, functions, etc. act like variables but how do these work?
Usually we (community) say the Pipe Operator |> is just a way, to write the last argument of a function before the function call. For example
f x y
can be written
y |> f x
but for correctness, this is not true. It just pass the next argument to a function. So you could even write.
y |> (x |> f)
All of this, and all other kind of operators works, because in F# all functions are curried by default. This means, there exists only functions with one argument. Functions with many arguments, are implemented that a functions return another function.
You could also write
(f x) y
for example. The function f is a function that takes x as argument and returns another function. This then gets y passed as an argument.
This process is automatically done by the language. So if you write
let f x y z = x + y + z
it is the same as:
let f = fun x -> fun y -> fun z -> x + y + z
Currying is by the way the reason why parenthesis in a ML-like language are not enforced compared to a LISP like language. Otherwise you would have needded to write:
(((f 1) 2) 3)
to execute a function f with three arguments.
The pipe operator itself is just another function, it is defined as
let (|>) x f = f x
It takes a value x as its first argument. And a function f as its second argument. Because operators a written "infix" (this means between two operands) instead of "prefix" (before arguments, the normal way), this means its left argument to the operator is the first argument.
In my opinion, |> is used too much by most F# people. It makes sense to use piping if you have a chain of operations, one after another. Typically for example if you have multiple list operations.
Let's say, you want to square all numbers in a list and then filter only the even ones. Without piping you would write.
List.filter isEven (List.map square [1..10])
Here the second argument to List.filter is a list that is returned by List.map. You can also write it as
List.map square [1..10]
|> List.filter isEven
Piping is Function application, this means, you will execute/run a function, so it computes and returns a value as its result.
In the above example List.map is first executed, and the result is passed to List.filter. That's true with piping and without piping. But sometimes, you want to create another function, instead of executing/running a function. Let's say you want to create a function, from the above. The two versions you could write are
let evenSquares xs = List.filter isEven (List.map square xs)
let evenSquares xs = List.map square xs |> List.filter isEven
You could also write it as function composition.
let evenSquares = List.filter isEven << List.map square
let evenSquares = List.map square >> List.filter isEven
The << operator resembles function composition in the "normal" way, how you would write a function with parenthesis. And >> is the "backwards" compositon, how it would be written with |>.
The F# documentation writes it the other way, what is backward and forward. But i think the F# language creators are wrong.
The function composition operators are defined as:
let (<<) f g x = f (g x)
let (>>) f g x = g (f x)
As you see, the operator has technically three arguments. But remember currying. When you write f << g, then the result is another functions, that expects the last argument x. Passing less arguments then needed is also often called Partial Application.
Function composition is less often used in F#, because the compiler sometimes have problems with type inference if the function arguments are generic.
Theoretically you could write a program without ever defining a variable, just through function composition. This is also named Point-Free style.
I would not recommend it, it often makes code harder to read and/or understand. But it is sometimes used if you want to pass a function to another
Higher-Order function. This means, a functions that take another function as an argument. Like List.map, List.filter and so on.
Pipes and composition operators have simple definition but are difficult to grasp. But once we have understand them, they are super useful and we miss them when we get back to C#.
Here some explanations but you get the best feedbacks from your own experiments. Have fun!
Pipe right operator |>
val |> fn ≡ fn val
Utility:
Building a pipeline, to chain calls to functions: x |> f |> g ≡ g (f x).
Easier to read: just follow the data flow
No intermediary variables
Natural language in english: Subject Verb.
It's regular in object-oriented code : myObject.do()
In F#, the "subject" is usually the last parameter: List.map f list. Using |>, we get back the natural "Subject Verb" order: list |> List.map f
Final benefit but not the least: help type inference:
let items = ["a"; "bb"; "ccc"]
let longestKo = List.maxBy (fun x -> x.Length) items // ❌ Error FS0072
// ~~~~~~~~
let longest = items |> List.maxBy (fun x -> x.Length) // ✅ return "ccc"
Pipe left operator <|
fn <| expression ≡ fn (expression)
Less used than |>
✅ Small benefit: avoiding parentheses
❌ Major drawback: inverse of the english natural "left to right" reading order and inverse of execution order (because of left-associativity)
printf "%i" 1+2 // 💥 Error
printf "%i" (1+2) // With parentheses
printf "%i" <| 1+2 // With pipe left
What about this kind of expression: x |> fn <| y ❓
In theory, allow using fn in infix position, equivalent of fn x y
In practice, it can be very confusing for some readers not used to it.
👉 It's probably better to avoid using <|
Forward composition operator >>
Binary operator placed between 2 functions:
f >> g ≡ fun x -> g (f x) ≡ fun x -> x |> f |> g
Result of the 1st function is used as argument for the 2nd function
→ types must match: f: 'T -> 'U and g: 'U -> 'V → f >> g :'T -> 'V
let add1 x = x + 1
let times2 x = x * 2
let add1Times2 x = times2(add1 x) // 😕 Style explicit but heavy
let add1Times2' = add1 >> times2 // 👍 Style concise
Backward composition operator <<
f >> g ≡ g << f
Less used than >>, except to get terms in english order:
let even x = x % 2 = 0
// even not 😕
let odd x = x |> even |> not
// "not even" is easier to read 👍
let odd = not << even
☝ Note: << is the mathematical function composition ∘: g ∘ f ≡ fun x -> g (f x) ≡ g << f.
It's confusing in F# because it's >> that is usually called the "composition operator" ("forward" being usually omitted).
On the other hand, the symbols used for these operators are super useful to remember the order of execution of the functions: f >> g means apply f then apply g. Even if argument is implicit, we get the data flow direction:
>> : from left to right → f >> g ≡ fun x -> x |> f |> g
<< : from right to left → f << g ≡ fun x -> f <| (g <| x)
(Edited after good advices from David)
The F# pipe-forward can be expressed as:
let (|>) x f = f x
For example:
let SimpleFunction (a : typeA) (b : typeB) (c : typeC)=
printf "OK."
// No problem here.
SimpleFunction a b c
// Using pipe-forward
c |> SimpleFunction a b
// No problem here. Interpreted as the same as above.
However, according to the documentation, the pipe-forward operator is left-associative.
https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/symbol-and-operator-reference/
So, I expected the pipe-forward statement:
// Original Expression
c |> SimpleFunction a b
// to be equivalent to:
(c |> SimpleFunction) a b
// Which is equivalent to:
SimpleFunction c a b
// Error!! SimpleFunction takes typeA, then typeB, then typeC.
Why does the compiler not "interpret" the pipe-forward expression as the error expression? Do I have any confusion about the operator precedence/associativity?
Additional Sources:
http://theburningmonk.com/2011/09/fsharp-pipe-forward-and-pipe-backward/
What is associativity of operators and why is it important?
https://en.wikipedia.org/wiki/Operator_associativity
The associativitity of a binary operator only matters when you have two or more occurrences of the same operator. When you have different operators (here: |> and juxtaposition), what matters is their relative precedence.
Juxtaposition has a higher precedence than |>, therefore
c |> SimpleFunction a b
is parsed like
(c) |> (SimpleFunction a b)
so, by the definition of |>, it's equivalent to
(SimpleFunction a b) (c)
which would usually be written
SimpleFunction a b c
That last equivalence is due to juxtaposition being left-associative.
The fact that |> is left-associative means that an expression like
x |> f |> g
is parsed as
(x |> f) |> g
which is equivalent to
g (f x)
i.e. chains of |> express function composition — successive pipeline steps — and not passing more arguments to a function.
Functions are curried by default, you original expression is actually like this:
c |> (SimpleFunction a b) which then becomes (SimpleFunction a b) c. For this to work function application will have to have precedence.
Frequently one wants to iterate (with either map, iter, or fold) through a collection of heterogeneous objects (different types). One way to deal with this is to create a discriminated union, which allows one to create a list with the objects suitably converted to DU cases. The following code does that in a simple example:
type MYDU = | X1 of int
| X2 of float
| X3 of string
let bar (y: MYDU) =
match y with
| X1 x -> printfn "%A" x
| X2 x -> printfn "%A" x
| X3 x -> printfn "%A" x
[X1(1); X2(2.0); X3("3"); X1(4)]
|> List.map bar |> ignore
This code runs fine and prints
1
2.0
"3"
4
Great! But I wonder if one can avoid repeating the call to printfn. I tried the following and it does not compile:
let baz (y: MYDU) =
match y with
| X1 x | X2 x | X3 x -> printfn "%A" x // red squiggly line under X1 x
The compiler issues this message:
This expression was expected to have type 'int' but here has type 'float'
I suspect avoiding repetition is feasible but I must be making a basic mistake. Any suggestions?
You're not making a mistake there, it's just not something F#'s type system would allow.
You can have multiple patterns on the left side of the match case arrow, but they are required to bind the same set of values (incl. the types). Here, x has a different type for each pattern, and that's enough for the compiler to complain.
There are ways to alleviate the pain (you could have a member on the DU that would return a boxed value, or you could have an active pattern that would do the boxing in the match case), but they're highly situational. Splitting the patterns into separate cases and repeating the right side for each one of them is always a better solution in a vacuum.
Something you could do instead is convert your arguments to a common type for printing, then print that value out instead. And you still get the advantages of pattern matching and discriminated unions :)
Here is an example of this approach
type MYDU =
| X1 of int
| X2 of float
| X3 of string
let bar y =
let myStr =
match y with
| X1 x -> string x
| X2 x -> string x
| X3 x -> x
printfn "%s" myStr
bar (X1 5)
It is possible to avoid this repetition to some degree by "boxing" the values to the obj type. This is an alias for the .NET's System.Object: "the ultimate base class of all classes in the .NET Framework". This means that any value of any type is also an obj.
However, when you box an object you lose static typing. You are subverting the F# type system and increasing the chance of an error. This is why it should generally be avoided unless you have a good reason for doing so.
The function printfn "%A" can take any type so its type signature is effectively obj -> unit. If all you want to do is run this function on the value, then it might be considered reasonable to use boxing. You could define this active pattern, which uses the box function:
let (|Box|) x = box x
And then use the pattern like this:
let printMyDu myDu =
match myDu with
| X1 (Box x)
| X2 (Box x)
| X3 (Box x) -> printfn "%A" x
Again, you should avoid doing this if possible as you are losing type safety in many cases. For example, if you ever box a value only to later check which type the value is, you are probably taking the wrong approach for F#. In this example we box the value x and then immediately use it and discard it, so we don't reduce overall type safety.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
When passing a function to another function which should calculate the result and then pass that value as an argument to another function, I've discovered that I could "compose" the following code in 5 different ways.
let testnum testFun =
testFun 4
printfn "result: %b" (testnum (=) 0)
printfn "result: %b" <| testnum (<) 0
printfn "result: %b" (testnum <| (>=) 0)
testnum <| (=) 0 |> printfn "result: %b"
printfn "resutl: %b" << testnum <| (<>) 0
I do like the style without parentheses more but now I'm wondering, is there a preferred style assuming my goal is readability and supportability of my code?
For your example I would have picked the first one:
printfn "result: %b" (testnum (=) 0)
The second one is passable:
printfn "result: %b" <| testnum (<) 0
The others are too contrived, they look like exercise in obfuscation.
I do use "backward" pipe operator exclusively in two situations:
when I have a type constructor that would need nested parentheses otherwise, so Some <| Foo ("bar", "baz") instead of Some (Foo ("bar", "baz"))
when I want to pass a single anonymous function as a last argument - it communicates nicely where the action is at:
lock sync <| fun () ->
...
For what is worth, if there are multiple anonymous functions passed as arguments, I would usually parenthesize each one of them instead (the notable exception being when one of them is a few characters long one liner and the other has multiple lines - then I would still go with the above syntax).
As for pipelining, I would usually go with |> for longer pipelines, and use function composition >> for shorter ones, when I don't need to refer to the argument again in the body of the function.
I don't think I would ever put |> and <| in the same line without parenthesizing one of them. It just looks odd.
Prefer pipe |>, this help with inference and readability
(=) 3 |> testnum |> printfn "result: %b"
you can easy break it on multiple lines
(=) 3
|> testnum
|> printfn "result: %b"
if arguments are few, you can pass them directly
testnum (=) 4 |> printfn "result: %b"
but use pipe |> or composition >> like g x |> f or x |> g |> f instead of nested function call f(g(x)), is more idiomatic. This also help with inference, for example instead of the . operator
open System.Linq
let double x = x * 2
let double1 items = items |> Seq.map double
[1;2;3] |> double1 |> printfn "%A"
//this doesn't compile,
//error: Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed ..
//
// let double2 items = items.Select(double)
// [1;2;3] |> double2 |> printfn "%A"
let double3 (items:seq<_>) = items.Select(double)
[1;2;3] |> double3 |> printfn "%A"
example: https://dotnetfiddle.net/K0u3NQ
In C#, you can express characters for the KeyPress event in the form Keys.Control | Keys.M. In F#, Keys.Control ||| Keys.M doesn't work. What does?
Edit: Interesting indeed. Using System.Windows.Forms.Keys.Control ||| System.Windows.Forms.Keys.M as per Johannes Rössel's suggestion below in the F# interactive window works exactly as he shows. Writing it in a .fs file:
form.KeyPress.Add (fun e ->
if (e.KeyChar = (System.Windows.Forms.Keys.Control ||| System.Windows.Forms.Keys.M)) then textbox.SelectAll() )
gives me the error The type 'char' does not support any operators named '|||'. So I probably misidentified the location of the problem. There is no typecasting from Keys to char.
Just little addition to Johaness Rössel's answer, there is nicer (or 'more functional') way to do this using reactive programming.
form.KeyDown
|> Event.filter (fun e -> e.KeyData = (Keys.Control + Keys.M))
|> Event.map (fun _ -> textbox.SelectAll())
|> ignore
Use +:
Keys.Control + Keys.M
FWIW, ||| works for me, though:
> System.Windows.Forms.Keys.Control ||| System.Windows.Forms.Keys.M;;
val it : System.Windows.Forms.Keys = M, Control