F# noob help understanding Lazy and Value - f#

I'm just beginning F# and haven't really done functional programming since my programming languages class 15 years ago (exception being "modern" C#).
I'm looking at this F# snippet using LINQPad 4:
let add x y = x + y
let lazyPlusOne x = lazy add x 1
let e = lazyPlusOne 15
Dump e
let plusOne x = add x 1
let f = plusOne 15
Dump f
The output it produces is:
Lazy<Int32>
Value is not created.
IsValueCreated False
Value 16
16
I understand the lazy keyword to delay evaluation until needed, same as C# delayed execution.
What is the meaning of: "Value is not created" here?

If you use lazy keyword to construct a lazy value (as in your lazyPlusOne function), then the result is a value of type Lazy<int>. This represents a value of type int that is evaluated only when it is actually needed.
I assume that Dump function tries to print the value including all its properties - when it starts printing, the value is not evaluated, so ToString method prints Value is not created. Then it iterates over other properties and when it accesses Value, the lazy value is evaluated (because its value is now needed). After evaluation, the property returns 16, which is then printed.
You can replace Dump with an F#-friendly printing function (or just use F# Interactive, which is extremely convenient way to play with F# inside Visual Studio with the usual IntelliSense, background error checking etec.)
F#-friendly printing function like printfn "%A" doesn't access the Value property, so it doesn't accidentally evaluate the value. Here is a snippet from F# Interactive:
> let a = lazy (1 + 2);;
val a : Lazy<int> = Value is not created. // Creates lazy value that's not evaluated
> a;;
val it : Lazy<int> = Value is not created. // Still not evaluated!
> a.Value;; // Now, the lazy value needs to be evaluated (to get the Value)
val it : int = 3
> a;; // After evaluation, the value stays cached
val it : Lazy<int> = 3

As of 'Dump e', 'lazyPlusOne 15' has not been evaluated. The 'let e = lazyPlusOne 15' does not require the evaluation of 'lazyPlusOne 15'. We don't yet need to know what e evaluates to yet.
The dump is triggering the evaluation and that is semantically different that just dumping the value after the evaluation.

Related

This expression was expected to have type bool but here has type unit error

getting an error when I try to run this line of code and I can't figure out why
let validCol column value : bool =
for i in 0..8 do
if sudokuBoard.[i,column] = value then
false
else true
As Tyler Hartwig says a for loop cannot return a value except unit.
On the other hand, inside a list comprehension or a seq Computation Expression you can use for to yield the values and then test if the one you are looking for exists:
let validCol column value : bool =
seq { for i in 0..8 do yield sudokuBoard.[i,column] }
|> Seq.exists value
|> not
In F#, the last call made is what is returned, you have explicitly declared you are returning a bool.
The for loop is unable to return or aggregate multiple values, bun instead, returns unit.
let validCol column value : bool =
for i in 0..8 do
if sudokuBoard.[i,column] = value then
false
else
true
Here, you'll need to figure out how to aggregate all the bool to get your final result. I'm not quite sure what this is supposed to return, or I'd give an example.
It looks like you are looking for a short-cut out of the loop like in C# you can use continue, break or return to exit a loop.
In F# the way to accomplish that with performance is to use tail-recursion. You could achieve it with while loops but that requires mutable variables which tail-recursion doesn't need (although we sometimes uses it).
A tail-recursive function is one that calls itself at the very end and doesn't look at the result:
So this is tail-recursive
let rec loop acc i = if i > 0 then loop (acc + i) (i - 1) else acc
Where this isn't
let rec loop fib i = if i < 1 then 1 else fib (i - 1) + fib (i - 2)
If F# compiler determines a function is tail-recursive the compiler applies tail-recursion optimization (TCO) on the function, basically it unrolls it into an efficient for loop that looks a lot like the loop would like in C#.
So here is one way to write validCol using tail-recursion:
let validCol column value : bool =
// loops is tail-recursive
let rec loop column value i =
if i < 9 then
if sudokuBoard.[i,column] = value then
false // The value already exists in the column, not valid
else
loop column value (i + 1) // Check next row.
else
true // Reach the end, the value is valid
loop column value 0
Unfortunately; F# compiler doesn't have an attribute to force TCO (like Scala or kotlin does) and therefore if you make a slight mistake you might end up with a function that isn't TCO. I think I saw GitHub issue about adding such an attribute.
PS. seq comprehensions are nice in many cases but for a sudoku solver I assume you are looking for something that is as fast as possible. seq comprehensions (and LINQ) I think adds too much overhead for a sudoku solver whereas tail-recursion is about as quick as you can get in F#.
PS. In .NET 2D arrays are slower than 1D arrays, just FYI. Unsure if it has improved with dotnet core.

Entry point issue in F#

I have the following program :
let readStoriesInQAForm =
printfn "Inside the let!"
0
[<EntryPoint>]
let main argv =
printfn "Ah! entering point to the main!"
System.Console.ReadKey() |> ignore
0 // return an integer exit code
I was expecting to get the following output (since main is the entry point, and there is no function call):
Ah! entering point to the main!
But I get this, when I compiler and run it in VS 2013:
Inside the let!
Ah! entering point to the main!
What is my mistake?
As John Palmer describes in his answer, F# code is executed from top to bottom. The let keyword binds a value to a name - in this case, the value 0 is bound to the readStoriesInQAForm name.
Apart from primitive values, you can also bind functions to names; F# is a Functional programming language, so functions are values too. If you bind a function to a name, you can execute that function by invoking it.
However, readStoriesInQAForm isn't a function - it's a primitive value (0), and it gets bound before main is called, in order to make that value available for main. In this particular case, the way the let binding is defined, it has a side-effect of printing to Standard Out when the binding occurs. (In general, in Functional Programming, the more you can avoid side-effects, the better.)
If you want to avoid this behaviour, change the let binding from a a primitive value to a function:
let readStoriesInQAForm () =
printfn "Inside the let!"
0
Better yet would be to bind the name to the value without any side-effect:
let readStoriesInQAForm = 0
In a F# program, the code is essentially run from top to bottom, so that any values needed later are available.
For example, if you had written:
[<EntryPoint>]
let main argv =
printfn "Ah! entering point to the main!"
printfn readStoriesInQAForm
System.Console.ReadKey() |> ignore
0 // return an integer exit code
The observed behaviour makes perfect sense as it would be illogical to jump out of main to calculate a constant value.
To avoid this issue, you want to make readStoriesInQAForm a function, like so:
let readStoriesInQAForm() = ...
You're not declaring a function, you're declaring a value. It's missing ():
let readStoriesInQAForm() =

value restriction case in F#

I am puzzled as to why the 3rd function would not work :
let generate1 = id
let generate2 = let a = 1
id
let generate3 = printfn "hi"
id
while the first 2 are fine, the last one spits out
error FS0030: Value restriction. The value 'generate3' has been inferred to have generic type
val generate3 : ('_a -> '_a)
Either make the arguments to 'generate3' explicit or, if you do not intend for it to be generic, add a type annotation.
I won't attempt to explain value restriction, but I will attempt to sort out the semantic differences between these three values.
generate1 is just an alias for id, so we're good there.
generate3 does some computations before returning id, hitting value restriction.
Then why doesn't generate2 hit value restriction like generate3? Because the compiler can see that let x = 1 in id is semantically equivalent to just id: 1 is a constant expression and x not used in the body of the let ... in ... expression, so the compiler can and does throw them away. On-the-other-hand, if you replace 1 with a potential side-effect like sin 2.3 (sin is pure, but the compiler can't prove it), then the compiler can't safely reduce the expression, thus hitting value restriction as with generate3.

300 milliseconds just for a variable declaration in F# Interactive?

I am playing with the F# Interactive Console and comparing the runtime of some numeric operations. On this code the total runtime seems to double only be repeating the declaration of one variable.
In VS 2010 I do:
open System.Diagnostics
let mutable a=1
Then I select this below and run it with Alt+Enter
let stopWatch = Stopwatch.StartNew()
for i=1 to 200100100 do
a <- a + 1
stopWatch.Stop()
printfn "stopWatch.Elapsed: %f" stopWatch.Elapsed.TotalMilliseconds
it takes more or less: 320 ms
now i select this and hit Alt+Enter:
let mutable a=1
let stopWatch = Stopwatch.StartNew()
for i=1 to 200100100 do
a <- a + 1
stopWatch.Stop()
printfn "stopWatch.Elapsed: %f" stopWatch.Elapsed.TotalMilliseconds
almost double: 620 ms
The same block but including the declaration at the top takes almost double. Shouldn't it be the same since I declare the variable before Stopwatch.StartNew() ? Does this have to do with the interactive console?
I have the same results using the #time directive.
I'm not convinced any of the answers yet are quite right. I think a is represented the same in both cases. And by that I mean an individual type is emitted dynamically wrapping that mutable value (certainly on the heap!). It needs to do this since in both cases, a is a top-level binding that can be accessed by subsequent interactions.
So all that said, my theory is this: in the first case, the dynamic type emitted by FSI is loaded at the end of the interaction, in order to output its default value. In the second case, however, the type wrapping a is not loaded until it is first accessed, in the loop, after the StopWatch was started.
Daniel is right - if you define a variable in a separate FSI interaction, then it is represented differently.
To get a correct comparison, you need to declare the variable as local in both cases. The easiest way to do that is to nest the code under do (which turns everything under do into a local scope) and then evaluate the entire do block at once. See the result of the following two examples:
// A version with variable declaration excluded
do
let mutable a=1
let stopWatch = Stopwatch.StartNew()
for i=1 to 200100100 do
a <- a + 1
stopWatch.Stop()
printfn "stopWatch.Elapsed: %f" stopWatch.Elapsed.TotalMilliseconds
// A version with variable declaration included
do
let stopWatch = Stopwatch.StartNew()
let mutable a=1
for i=1 to 200100100 do
a <- a + 1
stopWatch.Stop()
printfn "stopWatch.Elapsed: %f" stopWatch.Elapsed.TotalMilliseconds
The difference I get when I run them is not measureable.

F# Lazy Evaluation vs Non-Lazy

I'm just beginning F# so please be kind if this is basic.
I've read that a function marked lazy is evaluated only once and then cached. For example:
let lazyFunc = lazy (1 + 1)
let theValue = Lazy.force lazyFunc
Compared to this version which would actually run each time it's called:
let eagerFunc = (1 + 1)
let theValue = eagerFunc
Based on that, should all functions be made lazy? When would you not want to? This is coming from material in the book "Beginning F#".
First of all, it may be helpful to note that none of the things you have defined is a function - eagerFunc and theValue are values of type int and lazyFunc is a value of type Lazy<int>. Given
let lazyTwo = lazy (1 + 1)
and
let eagerTwo = 1 + 1
the expression 1 + 1 will not be evaluated more than once no matter how many times you use eagerTwo. The difference is that 1 + 1 will be evaluated exactly once when defining eagerTwo, but will be evaluated at most once when lazyTwo is used (it will be evaluated the first time that the Value property is accessed, and then cached so that further uses of Value do not need to recalculated it). If lazyTwo's Value is never accessed, then its body 1 + 1 will never be evaluated.
Typically, you won't see much benefit to using lazy values in a strict language like F#. They add a small amount of overhead since accessing the Value property requires checking whether the value has already been calculated. They might save you a bit of calculation if you have something like let lazyValue = lazy someVeryExpensiveCalculationThatMightNotBeNeeded(), since the expensive calculation will only take place if the value is actually used. They can also make some algorithms terminate which otherwise would not, but this is not a major issue in F#. For instance:
// throws an exception if x = 0.0
let eagerDivision x =
let oneOverX = 1.0 / x
if x = 0.0 then
printfn "Tried to divide by zero" // too late, this line is never reached
else
printfn "One over x is: %f" oneOverX
// succeeds even if x = 0.0, since the quotient is lazily evaluated
let lazyDivision x =
let oneOverX = lazy (1.0 / x)
if x = 0.0 then
printfn "Tried to divide by zero"
else
printfn "One over x is: %f" oneOverX.Value
If function executions have side-effects and it is important to see the side-effects each time the function is called (say it wraps an I/O function) you would not want it to be lazy.
There are also functions that are so trivial that executing them each time is faster than caching the value--
let eagerFunc = (1 + 1) is a let binding, and will only execute once. let eagerFunc() = (1 + 1) is a function accepting unit (nothing) and returning an int. It will execute each time it's called. In a sense, every function is lazy, that is, it only executes when called. However, the lazy keyword (and System.Lazy, which it returns) will execute the expression/function given to it at most once. Subsequent calls to the Value property will return the cached result. This is useful when computation of the value is expensive.
Many functions will not be suitable for use with lazy because they are either non-deterministic (may return a different result with each invocation) or parameterized. Of course, it's possible to use a fully-applied (a value is supplied for each parameter) version of such functions, but generally the variability is desired.

Resources