This question already has answers here:
F# Functions vs. Values
(4 answers)
Closed 8 years ago.
Newby question f# related,
What is the difference between this definitions in f# ?
module s
let log p =
printfn "expression is %A" p
let loggedWorkflow =
let x = 42
log x
let y = 43
log y
let z = x + y
log z
z
s.loggedWorkflow
and this one
module s
let log p =
printfn "expression is %A" p
let loggedWorkflow() =
let x = 42
log x
let y = 43
log y
let z = x + y
log z
z
s.loggedWorkflow()
The first one does not call the inner log, only returns z value
Why it works this way?
Thanks :)
I take this sample from
http://fsharpforfunandprofit.com/posts/computation-expressions-intro/
let loggedWorkflow = ... is defining a value. The body is evaluated as soon as the definition is reached (typically when the module s is loaded), and the value of loggedWorkflow is remembered as the result of evaluating the body, and returned every time someone evaluates s.loggedWorkflow.
let loggedWorkflow() = ... is defining a function that takes a single argument of type unit - the only value of this type is (), also typically pronounced "unit". The body doesn't get evaluated straight away, but only when the function is actually called. Each time it is called by actually passing an argument of type unit, e.g. with s.loggedWorkflow(), the body is evaluated and the resulting value returned.
Related
I'm reading through an F# tutorial, and ran into an example of syntax that I don't understand. The link to the page I'm reading is at the bottom. Here's the example from that page:
let rec quicksort2 = function
| [] -> []
| first::rest ->
let smaller,larger = List.partition ((>=) first) rest
List.concat [quicksort2 smaller; [first]; quicksort2 larger]
// test code
printfn "%A" (quicksort2 [1;5;23;18;9;1;3])
The part I don't understand is this: ((>=) first). What exactly is this? For contrast, this is an example from the MSDN documentation for List.partition:
let list1 = [ 1 .. 10 ]
let listEven, listOdd = List.partition (fun elem -> elem % 2 = 0) list1
printfn "Evens: %A\nOdds: %A" listEven listOdd
The first parameter (is this the right terminology?) to List.partition is obviously an anonymous function. I rewrote the line in question as this:
let smaller,larger = List.partition (fun e -> first >= e) rest
and it works the same as the example above. I just don't understand how this construct accomplishes the same thing: ((>=) first)
http://fsharpforfunandprofit.com/posts/fvsc-quicksort/
That's roughly the same thing as infix notation vs prefix notation
Operator are functions too and follow the same rule (ie. they can be partially applied)
So here (>=) first is the operator >= with first already applied as "first" operand, and gives back a function waiting for the second operand of the operator as you noticed when rewriting that line.
This construct combines two features: operator call with prefix notation and partial function application.
First, let's look at calling operators with prefix notation.
let x = a + b
The above code calls operator + with two arguments, a and b. Since this is a functional language, everything is a function, including operators, including operator +. It's just that operators have this funny call syntax, where you put the function between the arguments instead of in front of them. But you can still treat the operator just as any other normal function. To do that, you need to enclose it on parentheses:
let x = (+) a b // same thing as a + b.
And when I say "as any other function", I totally mean it:
let f = (+)
let x = f a b // still same thing.
Next, let's look at partial function application. Consider this function:
let f x y = x + y
We can call it and get a number in return:
let a = f 5 6 // a = 11
But we can also "almost" call it by supplying only one of two arguments:
let a = f 5 // a is a function
let b = a 6 // b = 11
The result of such "almost call" (technically called "partial application") is another function that still expects the remaining arguments.
And now, let's combine the two:
let a = (+) 5 // a is a function
let b = a 6 // b = 11
In general, one can write the following equivalency:
(+) x === fun y -> x + y
Or, similarly, for your specific case:
(>=) first === fun y -> first >= y
This question already has answers here:
What is currying in F#? [duplicate]
(5 answers)
Closed 6 years ago.
I am new to F# and I need an example of currying.
Is it currying or partial application?
let multiplyByThree x =
let multiply y =
y * x
multiply 3
let result = multiplyByThree 3 // 9
Partial application is a process, well, of creating partially applied function, e.g.:
let sum x y = x + y // sum is a curried function, it's default in F#
let sum4 x = sum 4 x // partial application
Currying is an ability to represent a function with multiple arguments as a sequence of functions taking single argument and returning a function as well.
However, if you're working with .NET functions, they accept their arguments as tuples, e.g.:
let sum (x,y) = x + y
// let sum4 x = sum 4 x // can't do that!
let sum4 x = sum (4,x) // this is valid. passing a tuple
I am a bit new to functional programming, and while I am somewhat familiar with F#, I am still learning about all the strange ways it works.
//I love my Rice and Curry'd functions
let add x =
let subFunction y =
x + y
subFunction
//explicit parameter
let add1 y = add 1 y
//implicit parameter
let add10 = add 10
//calling it with the parameter it doesn't show that it takes
let twenty = add10 10
So here add10 has implicit parameters by the fact that it is calling a function that returns a function that takes a parameter. Why is it accepted that I can declare it that way instead of the same way I declared add1?
It is really deceptive as judging by its declaration it, one would assume its just an int.
That's something coming from lambda calculus called eta-reduction
Basically it means that you can simplify your function/lambda by eliminating the last parameter on both sides of the expression when they are the same:
// instead of
let f x y = x + y
// in F# you can write
let f x y = (+) x y
// which is also the same as
let f x y = ((+) x) y
// then you can remove y
let f x = (+) x
// and then remove x
let f = (+)
In F# you can play with this as long as you don't reach the value restriction. So in your code let add1 y = add 1 y and let add10 = add 10 are equivalent. This is an example of how can you apply logic to reason about your code, applied to refactoring.
I've been trying to get my head round various bits of F# (I'm coming from more of a C# background), and parsers interest me, so I jumped at this blog post about F# parser combinators:
http://santialbo.com/blog/2013/03/24/introduction-to-parser-combinators
One of the samples here was this:
/// If the stream starts with c, returns Success, otherwise returns Failure
let CharParser (c: char) : Parser<char> =
let p stream =
match stream with
| x::xs when x = c -> Success(x, xs)
| _ -> Failure
in p //what does this mean?
However, one of the things that confused me about this code was the in p statement. I looked up the in keyword in the MSDN docs:
http://msdn.microsoft.com/en-us/library/dd233249.aspx
I also spotted this earlier question:
Meaning of keyword "in" in F#
Neither of those seemed to be the same usage. The only thing that seems to fit is that this is a pipelining construct.
The let x = ... in expr allows you to declare a binding for some variable x which can then be used in expr.
In this case p is a function which takes an argument stream and then returns either Success or Failure depending on the result of the match, and this function is returned by the CharParser function.
The F# light syntax automatically nests let .. in bindings, so for example
let x = 1
let y = x + 2
y * z
is the same as
let x = 1 in
let y = x + 2 in
y * z
Therefore, the in is not needed here and the function could have been written simply as
let CharParser (c: char) : Parser<char> =
let p stream =
match stream with
| x::xs when x = c -> Success(x, xs)
| _ -> Failure
p
The answer from Lee explains the problem. In F#, the in keyword is heritage from earlier functional languages that inspired F# and required it - namely from ML and OCaml.
It might be worth adding that there is just one situation in F# where you still need in - that is, when you want to write let followed by an expression on a single line. For example:
let a = 10
if (let x = a * a in x = 100) then printfn "Ok"
This is a bit funky coding style and I would not normally use it, but you do need in if you want to write it like this. You can always split that to multiple lines though:
let a = 10
if ( let x = a * a
x = 100 ) then printfn "Ok"
I'm using F# v 1.9.6.2, and I've defined a very simple computation expression:
type MaybeBuilder() =
member this.Let(x, f) =
printfn "this.Let: %A" x
this.Bind(Some x, f)
member this.Bind(x, f) =
printfn "this.Bind: %A" x
match x with
| Some(x) when x >= 0 && x <= 100 -> f(x)
| _ -> None
member this.Delay(f) = f()
member this.Return(x) = Some x
let maybe = MaybeBuilder()
I've sprinkled some print statements in the code to tell me which methods are being called in a computation expression. When I execute the following statement:
maybe {
let x = 12
let! y = Some 11
let! z = Some 30
return x + y + z
}
I expect the console to print out the following:
this.Let 12
this.Bind Some 12
this.Bind Some 11
this.Bind Some 30
But my actual results are as follows:
this.Bind: Some 11
this.Bind: Some 30
In other words, F# doesn't appear to be executing the Let member. When I re-write Let to throw an exception, the code run without an exception. Additionally, when I comment out the Let member entirely, I do not get an error message stating The field, constructor or member 'Let' is not defined, and the code executes as expected.
(I've tried investigating the code with Reflector, but as is usually the case, decompiled F# is mangled beyond readability.)
It looks like the spec for computation expressions has changed. Are let bindings no longer treated as syntax sugar, and is the Let members no longer required in computation workflows?
You had the answer yourself. From the F# spec that describes how computation expressions are translated:
{| let binds in cexpr |}C = let binds in {| cexpr |}C)
So no, you don't need to define let explicitly anymore, it's translated by the compiler.
Update: this change is mentioned in the detailed release notes of the September CTP.
Correct -- you can no longer provide a binding for let :(.
See also
http://cs.hubfs.net/forums/thread/6950.aspx