How to format a multi-line F# function in VisualStudio *.fsx - f#

Q1: I want to format an F# function over multiple lines in *.fsx in Visual Studio 2019, but when I try, I get syntax errors. (See below.)
Q2: In Haskell (as I recall) the order in which you declare functions doesn't matter. Is the same true in F#?
(*
2.3 Declare the F# function
isIthChar: string * int * char -> bool
where the value of isIthChar(str,i,ch) is true
if and only if ch is the i’th character in the string str
(numbering starting at zero).
Hansen, Michael R.. Functional Programming Using F# (p. 39). Cambridge University Press. Kindle Edition. *)
let isIthChar (str: string, i, ch) = (ch = str.[i])
(*
2.4 Declare the F# function
occFromIth: string * int * char -> int where
occFromIth(str, i, ch) =
the number of occurances of character ch
in positions j in the string str
with j >= i
Hint: the value should be 0 for i ≥ size str.
Hansen, Michael R.. Functional Programming Using F# (p. 39). Cambridge University Press. Kindle Edition.
*)
let rec countChar(str, i, j, ch, cnt) = if j < i then cnt else if isIthChar(str, j, ch) then countChar(str, i, j - 1, ch, cnt + 1) else countChar(str, i, j - 1, ch, cnt);; // all one line
let occFromIth(str, i, ch) = if (i >= String.length str) then 0 else countChar(str, i, (String.length str) - 1, ch, 0);; // all one line
//WANT something like:
let rec countChar(str, i, j, ch, cnt) = if j < i
then cnt
else if isIthChar(str, j, ch)
then countChar(str, i, j - 1, ch, cnt + 1)
else countChar(str, i, j - 1, ch, cnt);;
let occFromIth(str, i, ch) = if (i >= String.length str)
then 0
else countChar(str, i, (String.length str) - 1, ch, 0);;
// but these give syntax errors.
(* 2.5 Declare the F# function occInString: string * char -> int where
occInString(str, ch) = the number of occurences of a character ch in the string str.
Hansen, Michael R.. Functional Programming Using F# (p. 39). Cambridge University Press. Kindle Edition. *)
let occInString(str, ch) = occFromIth(str, 0, ch)

Formatting: then and else must be at least as far to the right as their preceding if, but in both your cases they're way to the left of it. Just move the if on the next line:
let rec countChar(str, i, j, ch, cnt) =
if j < i
then cnt
else if isIthChar(str, j, ch)
then countChar(str, i, j - 1, ch, cnt + 1)
else countChar(str, i, j - 1, ch, cnt)
Also note that double-semicolon is not necessary if the code is in an fsx file as opposed to being typed into FSI from keyboard.
Order of declaration: unlike Haskell, in F# all names must be defined before they're used, so your program reads top to bottom. This may seem limiting at first, but in practice it does wonders for code readability.
An exception to this rule is a group of mutually recursive functions (or types):
let rec f x = g (x+1)
and g x = f (x-1)
In this example g is used before it's defined.
Recently F# also got recursive modules, inside which all definitions are considered to be one large recursive group:
module rec A =
let f x = g (x+1)
let g x = f (x-1)
A few notes not strictly related to your questions:
else if can be abbreviated elif
While it's possible to define parameters as a tuple countChar(str, i, j, ch, cnt), it is customary (and vastly more convenient in practice) to define them in curried form countChar str i j ch cnt

Related

Finding an invariant for a simple loop

I have never felt so woefully inadequate as I am when trying to prove to Dafny that my program is correct, so I need your help: The given program looks as follows:
method doingMath(N: int, M: int) returns (s: int)
requires N <= M //given precondition
ensures 2*s == M*(M+1)-N*(N+1) //given postcondition
{
var a: int := N;
var r: int := 0;
while a < M
invariant FIND ME!
{
a := a+1;
r := r+a;
}
return r;
}
As first step I wanted to figure out what the loop does, so I made a table:
With that I worked out a loop invariant for r:
invariant r == (a-N)*N + (a-N)*((a-N)+1)/2
which holds before (0==0), and after each iteration of the loop (following the formula). Clearly it does not satisfy the Termination criteria
When the loop terminates, the loop invariant along with the reason that the loop terminated gives us a useful property.
Since the loop guard is simple enough I figured the complete invariant should be
invariant a<=M && r == (a-N)*N + (a-N)*((a-N)+1)/2
And thus my invariant satisfies Initialization, Maintenance and Termination. However Dafny complains that
Error: This loop invariant might not be maintained by the loop.
How do I make Dafny happy?
I managed to stay clear of any non-linear arithmetic hick-ups. Here's how I think of the problem:
You're trying to establish a postcondition that, for the sake of clarity, I will write as P(s, N, M), that is, some function of s, N, and M. One technique for coming up with a loop that does this is "replace a constant by a variable". What this means is that you pick one of the constants of the desired postcondition (here, you can choose either N or M, since s is not a constant) and replace it by a variable that is going to change in each loop iteration. Let's pick M as the constant and let's introduce (as you had already done in your program) a as the variable. Since we picked M as the constant, we'll want the final value of a to be M, so we'll start a at N. We then have:
method doingMath(N: int, M: int) returns (s: int)
requires N <= M
ensures P(s, N, M)
{
var a := N;
while a < M
invariant N <= a <= M
invariant P(s, N, a) // postcondition, but with variable a instead of constant M
}
If you type in this program (but expand out the P(s, N, a) to the actual condition), then you will find that Dafny proves the postcondition. In other words, the verifier is giving you the information that if you can establish and maintain this loop invariant, then the program will correctly establish the postcondition.
You can see this yourself, too. The negation of the loop guard gives you M <= a, which combined with the loop invariant a <= M gives you a == M. When you combine a == M and the loop invariant P(s, N, a), you get the postcondition P(s, N, M).
Great. But the verifier issues a complaint that the loop invariant does not hold on entry. This is because we didn't provide any initial value for s. Since a has the initial value N, we need to find a value for s that satisfies P(s, N, N). That value is 0, so we update the program to
method doingMath(N: int, M: int) returns (s: int)
requires N <= M
ensures P(s, N, M)
{
var a := N;
s := 0;
while a < M
invariant N <= a <= M
invariant P(s, N, a)
}
Next, let's write the loop body. (Notice how I have started with the loop invariant, rather than starting with loop body and then trying to figure out an invariant. For these sorts of programs, I find that's the easiest way.) We already decided that we want to vary a from the initial value N up to the final value M, so we add the assignment a := a + 1;:
method doingMath(N: int, M: int) returns (s: int)
requires N <= M
ensures 2*s == M*(M+1) - N*(N+1)
{
var a := N;
s := 0;
while a < M
invariant N <= a <= M
invariant P(s, N, a)
{
a := a + 1;
}
}
This addresses termination. The final thing we need to do is update s inside the loop so that the invariant is maintained. This is mostly easily done backward, in a goal-directed fashion. Here's how: At the end of the loop body, we want to make sure P(s, N, a) holds. That means we want the condition P(s, N, a + 1) to hold before the assignment to a. You obtain this condition (again, remember we're working backward) by replacing a in the desired condition with (the right-hand side of the assignment) a + 1.
Okay, so before the assignment to a, we want to have P(s, N, a + 1), and what we've got just inside the loop body is the invariant P(s, N, a). Now, it's time for me to expand P(...) to your actual condition. Alright, we have
2*s == a*(a+1) - N*(N+1) (*)
and we want
2*s == (a+1)*(a+2) - N*(N+1) (**)
Let's rewrite (a+1)*(a+2) in (**) as 2*(a+1) + a*(a+1). So, (**) can equivalently be written as
2*s == 2*(a+1) + a*(a+1) - N*(N+1) (***)
If you compare (***) (which is what we want) with (*) (which is what we've got), then you notice that the right-hand side of (***) is 2*(a+1) more than the right-hand side of (*). So, we must arrange to increase the left-hand side with the same amount.
If you increase s by a+1, then the left-hand side 2*s goes up by 2*(a+1), which is what we want. So, our final program is
method doingMath(N: int, M: int) returns (s: int)
requires N <= M
ensures 2*s == M*(M+1) - N*(N+1)
{
var a := N;
s := 0;
while a < M
invariant N <= a <= M
invariant 2*s == a*(a+1) - N*(N+1)
{
s := s + a + 1;
a := a + 1;
}
}
If you want, you can swap the order of the assignments to s and a. This will give you
method doingMath(N: int, M: int) returns (s: int)
requires N <= M
ensures 2*s == M*(M+1) - N*(N+1)
{
var a := N;
s := 0;
while a < M
invariant N <= a <= M
invariant 2*s == a*(a+1) - N*(N+1)
{
a := a + 1;
s := s + a;
}
}
In summary, we have built the loop body from the loop invariant, and we designed this loop invariant by "replacing a constant with a variable" in the postcondition.
Rustan
You are running afoul of the curse of nonlinear arithmetic. Any time you rely on nontrivial properties of multiplication, Dafny will have a hard time with your program.
Here is one way to fix your specific proof. Sorry that it is so messy. I'm sure it can be cleaned up, but I just hacked something together to show you the idea.
function {:opaque} mul(a: int, b: int): int
{
a * b
}
lemma MulZero1(a: int)
ensures mul(0, a) == 0
{
reveal mul();
}
lemma MulNeg1(a: int, b: int)
ensures mul(-a, b) == -mul(a, b)
{
reveal mul();
}
lemma MulNeg2(a: int, b: int)
ensures mul(a, -b) == -mul(a, b)
{
reveal mul();
}
lemma MulInd(a: nat, b: int)
ensures mul(a, b) == if a == 0 then 0 else mul(a-1, b) + b
{
reveal mul();
}
lemma MulEven(a: int, b: int)
requires b % 2 == 0
decreases if a < 0 then -a + 1 else a
ensures mul(a, b) % 2 == 0
{
if a < 0 {
MulNeg1(a, b);
MulEven(-a, b);
} else if a == 0 {
MulZero1(b);
} else {
calc {
mul(a, b) % 2;
{ MulInd(a, b); }
(mul(a-1, b) + b) % 2;
mul(a-1, b) % 2;
{ MulEven(a-1, b); }
0;
}
}
}
lemma MulComm(a: int, b: int)
ensures mul(a, b) == mul(b, a)
{
reveal mul();
}
lemma MulAdjEven(a: int)
ensures mul(a, a + 1) % 2 == 0
{
var m := a % 2;
if m == 0 {
MulComm(a, a+1);
MulEven(a+1, a);
} else {
assert m == 1;
assert (a + 1) % 2 == 0;
MulEven(a, a+1);
}
}
method doingMath(N: int, M: int) returns (s: int)
requires N <= M //given precondition
ensures 2*s == mul(M,M+1) - mul(N,N+1) //given postcondition
{
var a: int := N;
var r: int := 0;
assert mul(a-N, N) + mul(a-N, (a-N)+1)/2 == 0 by {
reveal mul();
}
while a < M
invariant a <= M
invariant r == mul(a-N, N) + mul(a-N, (a-N)+1)/2
{
a := a+1;
r := r+a;
assert r == mul(a-N, N) + mul(a-N, (a-N)+1)/2 by {
reveal mul();
}
}
calc {
2*r;
2* (mul(M-N, N) + mul(M-N, (M-N)+1)/2);
{ MulAdjEven(M-N); }
2*mul(M-N, N) + mul(M-N, (M-N)+1);
{ reveal mul(); }
mul(M,M+1) - mul(N,N+1);
}
return r;
}
Multiplication is hard for Dafny, so we manually wrap it in an opaque function. This gives us fine-grained control of when Dafny is allowed to "know" that the function is really multiplication.
Then we can replace all the occurrences of multiplication in your method by calls to mul. This makes Dafny fail quickly. (That's a big improvement over timing out!) Then we can selectively reveal the definition of mul where we need it, or we can prove lemmas about mul.
The hardest lemma is MulEven. Try replacing its body/proof by reveal mul(); and you will see that Dafny times out. Instead, I had to prove it by induction. This proof itself necessitated several other lemmas about multiplication. Fortunately, all of them were easy.
You may also want to take a look at the math library developed as part of the IronFleet project here. (Start by reading the files whose names contain the word "nonlinear"; those are the lowest-level proofs that are closest to the axioms.) They use a similar approach to build up a large body of facts about multiplication (and division and modulo), so that those functions can remain opaque everywhere else in the codebase, improving Dafny's performance.

F# return from loop

I have the following piece of C++ code that I am trying to implement in F#. I get an error message with F# segment (the line between the if statement). As I understand it, the statement "i" applies not to the function but to the "for" loop?
C++ code
int move( Board b )
{
for( int i = 0; i < b.size(); ++i )
if( b(i) != "*" )
return i;
return -1;
}
F# code
let move (board:array<string>) :int =
for i = 0 to (board.Length-1) do
if( Array.item(i) board <> "*" ) then
i
done
-1
You can't break a loop in F#, but don't worry, when you're used to F# you won't need to, it's actually easier:
let move (board:array<string>) :int =
match Array.tryFindIndex (fun e -> e <> "*") board with
| Some n -> n
| None -> -1

Pure pattern matching

I am building a function that counts of many times a character appears in a string after the nth position.
countCh ("aaabbbccc", 3, 'b')
val it: int = 2
In C, I would use an accumulator with a while loop. But I am trying to learn the F# functional face, where this approach is discouraged.
So I used guards to test few conditions and build the function:
let rec countCh (s:string, n:int, ch:char) =
match s, n, ch with
| (s, n, ch) when n > s.Length -> 0 //p1
| (s, n, ch) when n < 0 -> 0 //p2
| (s, n, ch) when s.[n] <> ch -> countCh(s, n + 1, ch) //p3
| (s, n, ch) when s.[n] = ch -> 1 + countCh(s, n + 1, ch) //p4
The coexistence of patterns 3 and 4 is problematic (impossible, I am afraid). Even if it compiles, I have not been able to make it work. How can this task functionally be handled?
First, the coexistence of these branches is not problematic. They don't conflict with each other. Why do you think that it's problematic? Is it because you get an "Incomplete pattern match" compiler warning? That warning does not tell you that the branches conflict, it tells you that the compiler can't prove that the four branches cover all possibilities. Or do you think that for some other reason? If you want your questions to be answered accurately, you'll have to ask them more clearly.
Second, you're abusing the pattern matching. Look: there are no patterns! The patterns in every branch are exactly the same, and trivial. Only guards are different. This looks very counterintuitively within a match, but would be plainly expressed with if..elif:
let rec countCh (s:string) n ch =
if n >= s.Length || n < 0 then 0
elif s.[n] = ch then 1 + countCh s (n + 1) ch
else countCh s (n + 1) ch
NOTE 1: see how I made the parameters curried? Always use curried form, unless there is a very strong reason to use tupled. Curried parameters are much more convenient to use on the caller side.
NOTE 2: your condition n > s.Length was incorrect: string indices go from 0 to s.Length-1, so the bail condition should be n >= s.Length. It is corrected in my code.
Finally, since this is an exercise, I must point out that the recursion is not tail recursion. Look at the second branch (in my code): it calls the function recursively and then adds one to the result. Since you have to do something with the result of the recursive call, the recursion can't be "tail". This means you risk stack overflow on very long inputs.
To make this into tail recursion, you need to turn the function "inside out", so to say. Instead of returning the result from every call, you need to pass it into every call (aka "accumulator"), and only return from the terminal case:
let rec countCh (s:string) n ch countSoFar =
if n >= s.Length || n < 0 then countSoFar
elif s.[n] = ch then countCh s (n+1) ch (countSoFar+1)
else countCh s (n+1) ch countSoFar
// Usage:
countCh "aaaabbbccc" 5 'b' 0
This way, every recursive call is the "last" call (i.e. the function doesn't do anything with the result, but passes it straight out to its own caller). This is called "tail recursion" and can be compiled to work in constant stack space (as opposed to linear).
I agree with the other answers, but I'd like to help you with your original question. You need to indent the function, and you have an off by one bug:
let rec countCh (s:string, n:int, ch:char) =
match s, n, ch with
| s, n, _ when n >= s.Length-1 -> 0 //p1
| s, _, _ when n < 0 -> 0 //p2
| s, n, ch when s.[n+1] <> ch -> countCh(s, n+2, ch) //p3
| s, n, ch when s.[n+1] = ch -> 1 + countCh(s, n+2, ch) //p4
I'd suggest to not write it yourself, but ask the library functions for help:
let countCh (s: string, n, c) =
s.Substring(n+1).ToCharArray()
|> Seq.filter ((=) c)
|> Seq.length
Or use Seq.skip, along with the fact that you can drop the conversion to character array:
let countCh (s: string, n, c) =
s
|> Seq.skip (n + 1)
|> Seq.filter ((=) c)
|> Seq.length

return value to break function

I am completely new to F# (started using it today) and relatively new to functional programming (I have minor experience with Lisp). I want to exit a function by returning a value when a certain condition is met so that the rest of the loop is not executed. Here is a C# illustration of what I want to do:
bool CheckRow (int n, int i)
{
for(int j = 0; j < 9; j++)
if (n == sudoku[i][j])
return false;
return true;
}
I tried implementing the same function in F# like this (sudoku is an array2D):
let CheckRow (n : int) (i : int) : bool =
for j = 0 to 8 do
if (n = sudoku.[i, j]) then
false
true
However, I get the following error at false within the if: "This expression was expected to have type unit but here has type bool". What is the proper way to "return" from within a F# function?
Higher-order functions are nice of course, but at some point someone has to write a loop (e.g. to implement the higher-order function), and that'll eventually be you, so it's nice to know how to write loops in F#. There is no early return from a for loop in F#, but other types of loops do allow this:
// While loop, imperative style
let checkRow n i =
let mutable clear = true
let mutable j = 0
while clear && j < 9 do
clear <- n <> sudoku.[i, j]
j <- j + 1
clear
// Tail-recursive style - more idiomatic F#
let checkRow n i =
let rec loop j =
if j = 9 then true
elif sudoku.[i, j] = n then false
else loop (j + 1)
loop 0
Normally you shouldn't need to break function earlier but rather end recursion on some case, otherwise call function recursively. Here recursion might be hidden because you are operating on lists or matrixes.
List.forall is one of those functions that implement recursion over the list and returns the result on the first occasion. You could write you function this way:
let CheckRow (expectedValue : int) (rowIndex : int) =
[0..8] |> List.forall (fun colIndex ->
sudoku.[rowIndex, colIndex] <> expectedValue)

Conversion from bool to int (true -> 1 and false -> 0)

Is there any built-in way in F# to convert from true to 1 and false to 0? This is simple in languages like C, C++ etc.
As a bit of background I am trying to solve an exercise in a textbook (exercise 2.4 in Functional Programming Using F#), which asks for an F# function occFromIth(str,i,ch) that returns the number of occurrences of character ch in positions j in the string str with j >= i.
My solution is
let rec occFromIth (str : string, i, ch) =
if i >= str.Length then 0
else if i < 0 || str.[i] <> ch then occFromIth(str, i+1, ch)
else 1 + occFromIth(str, i+1, ch)
but I don't like the code duplication so I wrote
let boolToInt = function
| true -> 1
| false -> 0
let rec occFromIth (str : string, i, ch) =
if i >= str.Length then 0
else boolToInt (not (i < 0 || str.[i] <> ch)) + occFromIth(str, i+1, ch)
I guess another alternative is to use if... then... else..., in the style of the C/C++ conditional operator
let rec occFromIth (str : string, i, ch) =
if i >= str.Length then 0
else (if (not (i < 0 || str.[i] <> ch)) then 1 else 0) + occFromIth(str, i+1, ch)
or
let rec occFromIth (str : string, i, ch) =
if i >= str.Length then 0
else (if (i < 0 || str.[i] <> ch) then 0 else 1) + occFromIth(str, i+1, ch)
What is the way to do this in F#?
System.Convert.ToInt32(bool) -- I'm not too familiar with F#, but I believe that using a function is the same whether it is built in or not: function(arg0, arg1, ...). So, in this case you'd simply call System.Convert.ToInt32(myBool).
You don't really need the bool to int or int to bool as you can achieve the result as:
let occFromIth (str : string, i, ch) =
str
|> Seq.mapi (fun j c -> (j,c))
|> Seq.filter (fun (j,c) -> j >= i && c = ch)
|> Seq.length
There is difference in making a function or using build in. The CPU instruction of any comparison return a result translated to the bit pattern for 1 and 0. This can be used to make branchless programming, which dependend on the situation are more effecient then branching. Comparison of to values can be found without branching
Int min(int a, int b) {
Int temp = a < b;
Return a*temp + b*(1-temp);
}

Resources