Error in pattern matching with LazyList in F# - f#

Trying to merge two LazyLists in F# after this question on SO. Originally wrote for matching two Lists. Modified that to get this:
let rec printLazyList (l1:LazyList<int>) (l2:LazyList<int>) =
match (l1, l2) with
| t, s when t |> LazyList.isEmpty && s |> LazyList.isEmpty -> printfn "";
| t , LazyList.Cons(h2,t2) when t |> LazyList.isEmpty -> printf "%d " h2
let a = LazyList.empty
printLazyList a t2
| LazyList.Cons(h1,t1), s when s |> LazyList.isEmpty -> printf "%d " h1
let b = LazyList.empty
printLazyList t1 b
| LazyList.Cons(h1,t1), LazyList.Cons(h2,t2) -> if h1 = h2 then
printf "%d " h1
printLazyList t1 t2
elif h1 < h2 then
printf "%d " h1
printLazyList t1 l2
else
printf "%d " h2
printLazyList l1 t2
The problem is it is giving no output. None of the conditions are being satisfied (checked this by putting a |_,_ printfn "nothing matches" at the end of the pattern matching. Is there a fundamental difference in the cons that is used in LazyList versus the :: in the usual F# lists? Because this worked for normal lists (cf. the link above).
Sorry if this is again a really n00b question. FP is looking rather difficult at this point.

If you test the function using fsi, be careful since there is a lot of noise in fsi console and your eyes may skip the line of output.
Here is a complete test (I did some cleanups by using Nil instead of isEmpty and reorganizing pattern matching for readability):
#r "FSharp.PowerPack.dll"
open LazyList
let rec printLazyList l1 l2 =
match l1, l2 with
| Nil, Nil -> printfn ""
| Nil, Cons(h2, t2) ->
printf "%d " h2
printLazyList LazyList.empty t2
| Cons(h1, t1), Nil ->
printf "%d " h1
printLazyList t1 LazyList.empty
| Cons(h1, t1), Cons(h2, t2) when h1 = h2 ->
printf "%d " h1
printLazyList t1 t2
| Cons(h1, t1), Cons(h2, t2) when h1 < h2 ->
printf "%d " h1
printLazyList t1 l2
| Cons(h1, t1), Cons(h2, t2) ->
printf "%d " h2
printLazyList l1 t2
let x = LazyList.ofList [1; 2];;
let y = LazyList.ofList [3; 4];;
printLazyList x y;;

Related

F# pattern-matching gone wrong

I am just starting out with F# so this might be a trivial question but I am not able to understand why the pattern matching in my code acts as it does.
Quick explanation of the code:
The func calcNextMatch should recurse a list and if 2 elements are equal they should be added together.
In the end the func should return a number that is the addition of all digits that has a match with the next digit in the list.
f.ex. [1;3;2;2;5] should return 4
Code:
let rec printList l =
match l with
| head :: tail -> printf "%d " head; printList tail
| [] -> printfn ""
let rec calcNextMatch list =
printList list
match list with
| [] -> 0
| _ :: tail ->
printList tail
let h = Seq.head list
let t = Seq.tryHead tail
printfn "h: %i" h
printfn "t: %O" t
match t with
| Some h ->
printfn "TAIL t: %i is equal to HEAD h: %i" t.Value h
printfn "Calculation is: %i" (t.Value + h)
(t.Value + h) + calcNextMatch tail
| _ -> calcNextMatch tail
let sequence = [ 1;3;2;2;5 ]
let run = calcNextMatch sequence
When I run this code the problem is that the pattern-matching
does not work as I expect it.
f.ex this print output from running the script.
h: 1
t: Some(3)
TAIL t: 3 is equal to HEAD h: 3
this means that F# has matched
match t with
| Some h ->
in a case where t = Some(3) and h = 1
which translates to
match 3 with
| Some 1 ->
and that I do not understand.
The print before the matching states the value of t and h to 3 and 1 but in the pattern-matching the value of h has change to 3
How is this possible?
You can only pattern match against constant literals, otherwise the value get bounded as if was a new let-binding.
In these cases what you do normally is to add a when condition:
match t with
| Some x when x = h ->
Also notice that you can use pattern match further to simplify your code, for instance here:
| _ :: tail ->
printList tail
let h = Seq.head list
You can write:
| h :: tail ->
printList tail
Also all this portion:
| _ :: tail ->
printList tail
let h = Seq.head list
let t = Seq.tryHead tail
printfn "h: %i" h
printfn "t: %O" t
match t with
| Some h ->
printfn "TAIL t: %i is equal to HEAD h: %i" t.Value h
printfn "Calculation is: %i" (t.Value + h)
(t.Value + h) + calcNextMatch tail
becomes:
| h :: tail ->
printList tail
//printfn "h: %i" h
//printfn "t: %O" t
match tail with
| t::_ when t = h ->
printfn "TAIL t: %i is equal to HEAD h: %i" t h
printfn "Calculation is: %i" (t + h)
(t + h) + calcNextMatch tail
And you can unify all matches in one, so your whole function becomes:
let rec calcNextMatch list =
printList list
match list with
| [] -> 0
| h::x::tail when x = h -> x + h + calcNextMatch (x::tail)
| _::tail -> calcNextMatch tail
Finally, when you're done with debugging, you can remove the prints and since the last parameter of your function is the one you match against, you can use the keyword function, also use an as pattern to avoid reconstructing the list:
let rec calcNextMatch = function
| [] -> 0
| h::((x::_) as tail) when x = h -> x + h + calcNextMatch tail
| _::tail -> calcNextMatch tail

Feeding an array to printfn

I'm printing a Tic-Tac-Toe board. I have an array of characters for each cell of the board and a format string for the board. I'm currently doing:
let cells = [| 'X'; 'O'; 'X'; 'O'; 'X'; 'O'; ' '; ' '; ' ' |]
printfn ".===.===.===.\n\
| %c | %c | %c |\n\
.===.===.===.\n\
| %c | %c | %c |\n\
.===.===.===.\n\
| %c | %c | %c |\n\
.===.===.===.\n" cells.[0] cells.[1] cells.[2] cells.[3] cells.[4] cells.[5] cells.[6] cells.[7] cells.[8]
Is there a way to feed the cells array to printfn without explicitly enumerating all 9 items in the array? Could I use Array.fold or kprintf somehow?
Funk's answer is pretty good, but I think you can make it simpler by introducing a join function to concatenate elements (individual cells or rows) with separators between them and surrounding them.
let join s arr = sprintf "%s%s%s" s (String.concat s arr) s
Then you can do this:
cells
|> Seq.chunkBySize 3
|> Seq.map (Seq.map (sprintf " %c ") >> join "|")
|> Seq.map (fun s -> s + "\n")
|> join ".===.===.===.\n"
|> printfn "%s"
It's far from sexy, but there's a pattern to be found.
cells
|> Array.toList
|> List.chunkBySize 3
|> List.fold
(fun acc list -> acc +
(list |> List.fold (fun acc char -> acc + sprintf "| %c " char) "") +
"|\n.===.===.===.\n")
".===.===.===.\n"
|> printf "%s"
Every successive application of an argument to the function results in a different type. For example:
let f1 = printfn "%d %d %d" // f1 : int -> int -> int -> unit
let f2 = f1 0 // f2 : int -> int -> unit
let f3 = f2 1 // f3 : int -> unit
let r = f3 2 // r : unit
Notice how f1, f2, f3, and r all have different types. Different types mean that you can't shove them into a generic data structure, such as a list or a sequence.
(to be honest, there is a way to go about this using method overloads, but that tends to break the compiler and generally is not necessary for real applications)
I would rather go a different route:
for i in 0..2 do
printf ".===.===.===.\n|"
for j in 0..2 do
printf "%c |" cells.[i*3+j]
printfn ""
printfn ".===.===.===."

F# remove trailing space

I have this method that takes in a list and turns it into a bytecode string. It works the way I expect; however, I get one trailing space that I do not want. Question: how do I get rid of this last trailing 0?
Input: byteCode [SC 10; SC 2; SAdd; SC 32; SC 4; SC 5; SAdd; SMul; SAdd]
let rec byteCode (l : sInstr list) : string =
match l with
| [] -> ""
| (SC n :: l) -> "0 " + string n + " " + byteCode l
| (SAdd :: l) -> "1 " + byteCode l
| (SSub :: l) -> "2 " + byteCode l
| (SMul :: l) -> "3 " + byteCode l
| (SNeg :: l) -> "4 " + byteCode l
| (SLess :: l) -> "5 " + byteCode l
| (SIfze n :: l) -> "6 " + string n + " " + byteCode l
| (SJump n :: l) -> "7 " + string n + " " + byteCode l
This probably won't compile because I didn't give my entire program.
This returns: "0 10 0 2 1 0 32 0 4 0 5 1 3 1 "
I expect: "0 10 0 2 1 0 32 0 4 0 5 1 3 1"
Cases like this are usually signs that strings are concatenated in a way that is too naive. Consider first collecting all the individual components of your result and then calling the predefined String.concat function:
let byteCode (l : sInstr list) : string =
let rec byteCode' l =
match l with
| [] -> []
| (SC n :: l) -> "0" :: string n :: byteCode' l
| (SAdd :: l) -> "1" :: byteCode' l
| (SSub :: l) -> "2" :: byteCode' l
| (SMul :: l) -> "3" :: byteCode' l
| (SNeg :: l) -> "4" :: byteCode' l
| (SLess :: l) -> "5" :: byteCode' l
| (SIfze n :: l) -> "6" :: string n :: byteCode' l
| (SJump n :: l) -> "7" :: string n :: byteCode' l
l |> byteCode' |> String.concat " "
String.concat already only adds the separator string between the individual parts.
This is also much cleaner, because it keeps the implementation detail of the specific separator string out of your core logic and makes it much more easily replaceable - imagine the effort of simply changing it to two spaces in your function.
Alternatively, you can just use your existing function, and on the final resulting string call the .Trim() (or .TrimEnd()) method to remove (trailing) spaces.
You could avoid recursion in this manner:
let byteCode (l : sInstr list) : string =
let instrToString (bc : sInstr) : string =
match bc with
| (SC n) -> sprintf "0 %d" n
| (SAdd ) -> "1"
| (SSub ) -> "2"
| (SMul ) -> "3"
| (SNeg ) -> "4"
| (SLess ) -> "5"
| (SIfze n) -> sprintf "6 %d" n
| (SJump n) -> sprintf "7 %d" n
l |> List.map instrToString |> String.concat " "
Supposed sInstr is defined as:
type sInstr =
| SC of int
| SAdd
| SSub
| SMul
| SNeg
| SLess
| SIfze of int
| SJump of int
the functions to byteCodes and revserse could look like this:
let byteCode (l : sInstr list) : string =
let instrToString (bc : sInstr) =
(match bc with
| SC n -> [0; n]
| SAdd -> [1]
| SSub -> [2]
| SMul -> [3]
| SNeg -> [4]
| SLess -> [5]
| SIfze n -> [6; n]
| SJump n -> [7; n])
String.Join(" ", (l |> List.map instrToString |> List.fold (fun acc lst -> acc # lst) []))
let toInstr (bcString : string) : sInstr list =
let rec recToInstr bcList =
match bcList with
| [] -> []
| head :: tail ->
match head with
| "0" -> SC(Int32.Parse(tail.[0])) :: recToInstr (tail |> List.skip 1)
| "1" -> SAdd :: recToInstr tail
| "2" -> SSub :: recToInstr tail
| "3" -> SMul :: recToInstr tail
| "4" -> SNeg :: recToInstr tail
| "5" -> SLess :: recToInstr tail
| "6" -> SIfze(Int32.Parse(tail.[0])) :: recToInstr (tail |> List.skip 1)
| "7" -> SJump(Int32.Parse(tail.[0])) :: recToInstr (tail |> List.skip 1)
| _ -> []
recToInstr (bcString.Split(' ') |> Array.toList)

With leftOuterJoin, .DefaultIfEmpty() is unnecessary

The documentation for leftOuterJoin Query Expressions on MSDN repeatedly implies through the samples that when using leftOuterJoin .. on .. into .. that you must still use .DefaultIfEmpty() to achieve the desired effect.
I don't believe this is necessary because I get the same results in both of these tests which differ only in that the second one does not .DefaultIfEpmty()
type Test = A | B | C
let G = [| A; B; C|]
let H = [| A; C; C|]
printfn "%A" <| query {
for g in G do
leftOuterJoin h in H on (g = h) into I
for i in I.DefaultIfEmpty() do
select (g, i)}
printfn "%A" <| query {
for g in G do
leftOuterJoin h in H on (g = h) into I
for i in I do
select (g, i)}
// seq [(A, A); (B, null); (C, C); (C, C)]
// seq [(A, A); (B, null); (C, C); (C, C)]
1) Can you confirm this?
If that's right, I realized it only after writing this alternate type augmentation in an attempt to better deal with unmatched results and I was surprised to still see nulls in my output!
type IEnumerable<'TSource> with
member this.NoneIfEmpty = if (Seq.exists (fun _ -> true) this)
then Seq.map (fun e -> Some e) this
else seq [ None ]
printfn "%A" <| query {
for g in G do
leftOuterJoin h in H on (g = h) into I
for i in I.NoneIfEmpty do
select (g, i)}
// seq [(A, Some A); (B, Some null); (C, Some C); (C, Some C)]
2) Is there a way to get None instead of null/Some null from the leftOuterJoin?
3) What I really want to do is find out if there are any unmatched g
printfn "%A" <| query {
for g in G do
leftOuterJoin h in H on (g = h) into I
for i in I.NoneIfEmpty do
where (i.IsNone)
exists (true) }
I figured this next one out but it isn't very F#:
printfn "%A" <| query {
for g in G do
leftOuterJoin h in H on (g = h) into I
for i in I do
where (box i = null)
exists (true)}
Short version: Query Expressions use nulls. It's a rough spot in the language, but a containable one.
I've done this before:
let ToOption (a:'a) =
match obj.ReferenceEquals(a,null) with
| true -> None
| false -> Some(a)
This will let you do:
printfn "%A" <| query {
for g in G do
leftOuterJoin h in H on (g = h) into I
for i in I do
select ( g,(ToOption i))}
Which wraps every result in an option (since you don't know if there is going to be an I. It's worth noting that F# uses null to represent None at run-time as an optimization. So to check if this is indeed what you want, make a decision on the option, like:
Seq.iter (fun (g,h) ->
printf "%A," g;
match h with
| Some(h) -> printfn "Some (%A)" h
| None -> printfn "None")
<| query {
for g in G do
leftOuterJoin h in H on (g = h) into I
for i in I do
select ((ToOption g),(ToOption i))}

Match a number if it is multiple of 2

I'm learning f# and currently I'm with the match keyword. I'm modifying the next example, to print into the screen if a numbers is multiple of 2, it's mod is 0.
[<Literal>]
let Three = 3
let filter123 x =
match x with
// The following line contains literal patterns combined with an OR pattern.
| 1 | 2 | Three -> printfn "Found 1, 2, or 3!"
// The following line contains a variable pattern.
| var1 -> printfn "%d" var1
for x in 1..10 do filter123 x
I have modified it and coded an additional match for:
| x % 2 == 0 -> printfn "it's multiple of 2!"
But that doesn't work, it says that "%" it's an undefined symbol... any ideas? Thanks!
This is a classic Tim Toady. The other answers are perfectly correct. I would add a couple of variations:
// Eugene's answer
let filterEven1 x =
match x with
| _ when x % 2 = 0 -> printfn "%d is even!" x
| _ -> printfn "%d is not even" x
// equivalent to above, but with "function" match syntax
let filterEven2 = function
| x when x % 2 = 0 -> printfn "%d is even!" x
| x -> printfn "%d is not even" x
// variation on Gene's answer
let (|Even|Odd|) x =
if x % 2 = 0 then Even(x) else Odd(x)
let filterEven3 = function
| Even(x) -> printfn "%d is even!" x
| Odd(x) -> printfn "%d is not even" x
// probably how I would do it
let filterEven4 x =
match x % 2 with
| 0 -> printfn "%d is even!" x
| _ -> printfn "%d is not even" x
You cannot use an expression as a match case. Another alternative to a guarded pattern would be defining an active pattern:
let(|Even|Odd|) (x:int) =
if x % 2 = 0 then Even else Odd
and then using it as a normal pattern case
.......
| Even -> printfn "it's multiple of 2!"
.......
You need to use guarded pattern rule:
| _ when x % 2 = 0 -> printfn "it's multiple of 2!"

Resources