parsing error on guards - parsing

I'm implementing the merge subroutine of merge sort. I'm getting this error message when compiling: parse error on input |
merge :: [Int] -> [Int] -> [Int]
merge xs ys = go xs ys []
where go xs ys zs =
|null ys = zs ++ xs
|null xs = zs ++ ys
|(head xs) <= head ys = go (tail xs) ys (head xs : zs)
|otherwise = go xs (tail ys) (head ys : zs)
can anyone tell me why? Also is there a more succinct way of doing this? Thanks.

You can fix the syntactic error by removing the = after go xs ys zs - when defining something with guards, the = comes only after each guard, as you already have.
Apart from that, your code would be a lot cleaner if you used pattern-matching more. Instead of checking whether a list with null and then inspecting the head and tail, you can use the patterns [] to identify empty lists and (x:xs) to both identify non-empty lists and to bind the head and tail to the names x and xs, etc:
merge :: [Int] -> [Int] -> [Int]
merge xs ys = go xs ys []
where go xs [] zs = zs ++ xs
go [] ys zs = zs ++ ys
go (x:xs) (y:ys) zs
| x <= y = go xs (y:ys) (x:zs)
| otherwise = go (x:xs) ys (y:zs)

Related

Pairing list elements with indexes

Given a list of elements, I need to turn each element into a pair of the index number and the element. There are several ways to do it; this is the most concise I have found so far:
List.mapi (fun i x->i,x) xs
But is there a more concise/idiomatic way to do it? For example, does F# have some built-in function to turn two elements into a pair, some equivalent of the C++ make_pair?
There is a function in the standard library that does exactly that: List.indexed
Eight Ways to Write Indexed
As there is more than one way to do it (TIMTOWTDI) it is always good to learn about different approaches and it different pros and cons. Remember that there is never only one way to solve something. Here some examples you can learn from if you try to understand them.
1. The List Comprehension
let indexed1 xs =
let mutable idx = 0
[ for x in xs do
yield idx,x
idx <- idx + 1 ]
2. Ziping It!
let indexed2 xs =
List.zip
(List.init (List.length xs) id)
xs
3. Recursion
let indexed3 xs =
let rec cata idx xs =
match xs with
| [] -> []
| x::xs -> (idx,x) :: cata (idx+1) xs
cata 0 xs
4. Tail-Recursion
let indexed4 xs =
let rec loop idx result xs =
match xs with
| [] -> result
| x::xs -> loop (idx+1) ((idx,x) :: result) xs
List.rev (loop 0 [] xs)
5. Folding it
let indexed5 xs =
let mutable idx = -1
List.fold (fun state x ->
idx <- idx + 1
(idx,x) :: state
) [] xs
|> List.rev
6. Folding without mutable
let indexed6 xs =
List.fold (fun (idx,state) x ->
(idx+1), (idx,x) :: state
) (0,[]) xs
|> snd
|> List.rev
7. Folding it Backwards
let indexed7 xs =
let lastIdx = List.length xs - 1
List.foldBack (fun x (idx,xs) ->
(idx-1), ((idx,x) :: xs)
) xs (lastIdx,[])
|> snd
8. Arraying it
let indexed8 xs =
let arr = Array.ofList xs
let mutable result = []
for idx=(arr.Length - 1) downto 0 do
result <- (idx,arr.[idx]) :: result
result

rewriting a code using pattern matching F#

Hi Im very new to F# as well as programming. Im trying to learn it now and have enrolled to a course but i still dont seem to get it. pls help. Im trying to rewrite the following code:
let rec msort xs =
let sz = List.length xs
if sz < 2 then xs
else let n = sz / 2
let ys = xs. [0..n-1]
let zs = xs.[n..sz-1]
in merge (msort ys) (msort zs)
//************ Utility-funktion merge
let rec merge xs ys = if List.isEmpty xs then ys else if
List.isEmpty ys then xs else let x = List.head xs
let y = List.head ys
let xs = List.tail xs
let ys = List.tail ys
in if x < y then x :: merge xs (y::ys)
else y :: merge (x::xs) ys </i>
My solution - which isnt working:
let rec msort xs =
let sz = List.length xs
match sz with
| sz < 2 -> xs
|_ -> n = sz/2
let ys = xs. [0..n-1]
let zs = xs.[n..sz-1]
in merge (msort ys) (msort zs)
//************ Utility-funktinen merge
let rec merge xs ys = match xs with |[] -> [ys]
match ys with
|[] -> [xs] |_ ->
let x = List.head xs
let y = List.head ys
let xs = List.tail xs
let ys = List.tail ys if x < y then x :: merge xs (y::ys)
|_ ->
y :: merge (x::xs) y
Notice that you can match over two values by writing them in a tuple and instead of let-binding list head and tail you can use pattern matching on the 'shape' of the list directly in the guards although the fact that the same name it's used for the whole list and later for the tail is a bit unfortunate as it can lead to confusion, but it works fine because F# shadows the values:
let rec merge xs ys =
match (xs, ys) with
| [], _ -> ys
| _, [] -> xs
| x::xs, y::ys ->
if x < y then x :: merge xs (y::ys)
else y :: merge (x::xs) ys
let rec msort xs =
let sz = List.length xs
match sz with
| sz when sz < 2 -> xs
|_ ->
let n = sz/2
let ys = xs. [0..n-1]
let zs = xs.[n..sz-1]
merge (msort ys) (msort zs)
You were missing the keyword when in the conditions of the guards.
I also fixed some minor details in your original code.

Meaning of "==>" syntax in F#

Consider the following code in F#
let rec ordered xs =
match xs with
| [] | [_] -> true
| x1 :: x2 :: xs' -> x1 <= x2 && ordered (x2 :: xs')
and then
let rec insert x xs =
match xs with
| [] -> [x]
| y :: ys -> if x <= y then x :: y :: ys
else y :: insert x ys
and finally
let insertKeepsOrder (x : int) xs = ordered xs ==> ordered (insert x xs)
What i can not understand is the ==> meanning in the last line!!!
What is it?
The ==> operator is part of FsCheck. It is used to express a property that should hold only if some condition is true.
So in your example:
let insertKeepsOrder (x : int) xs = ordered xs ==> ordered (insert x xs)
This means ordered (insert x xs) should be true only if ordered xs is true.
You can read more about this in the "Conditional Properties" section of the FsCheck documentation.

Merge Two Lists in F# Recursively [duplicate]

This question already has answers here:
Merge two lists
(6 answers)
Closed 6 years ago.
I am looking to write a recursive function to merge to integer lists in F#
I started with this, but not sure what to do next.
let rec merge xs ys =
match xs with
| [] -> ys
|
let li = [1;3;5;7;]
let ll = [2;4;5;8;]
As I said in my comment, it's probably easiest if you pattern match on xs and ys simultaneously:
let rec merge xs ys =
match xs,ys with
| [],l | l,[] -> l
| x::xs', y::ys' ->
if x < y then x :: (merge xs' ys) //'
else y :: (merge xs ys') //'
I found a way that might suit what the asker wanted. I for one had to solve this very same problem and was barely given a week's worth of lessons on F# so the whole syntax wasn't discussed in class and when I saw the answer above the use of multiple matching ( match lst1, list2 with ... ) I recognized it's use instantly but the professor wouldn't allow it's use, therefor I had to come up with this other alternative. Even thought it's basically the same algorithm it uses more basic code. Just thought I should post it =)
let rec merge2 list1 list2 =
let head list = match list with | [] -> 0 | h::t -> h
let tail list = match list with | [] -> [] | h::t -> t
match list1 with
| [] -> []
| h::t ->
//list2's head is 0 then list is empty then return whats in the first list
//(i.e no more values of second list to compare)
if head list2 = 0 then list1
elif h < head list2 then h :: merge2 t list2
else head list2 :: merge2 list1 (tail list2)
You already have one of the base cases right: If xs is empty, just return ys.
Likewise, if ys empty, return xs.
For the case where both xs and ys are not empty, you need to look at xs's and ys's first elements (let's call them x and y):
If x is less than y, than it needs to be inserted before y in the final list. So you take y and prepend to the result of merging the tail of xs with ys (including y).
Otherwise y needs to come first. So prepend y to the result of merging xs (including x) with the tail of ys.
It's not recursive, but if the inputs aren't sorted:
let merge xs ys = (Seq.append xs ys) |> Seq.sort |> Seq.toList
I would use List.fold to do this:
let merge a b =
List.fold (fun acc x ->
if List.exists ((=)x) acc = false then
elem :: acc
else
acc
) (List.sort a) b
This may not be the fastest way to do it, though.
I don't think this is a recursion problem
let a = [1;3;5]
let b = [2;4;6]
let c = Seq.append a b |> Seq.sort
output from fsi session:
c:
val it : seq<int> = seq [1; 2; 3; 4; ...]

Quicksort in F# - syntax question

I have a simple f# quick sort function defined as:
let rec qsort(xs:List<int>) =
let smaller = xs |> List.filter(fun e -> e < xs.Head)
let larger = xs |> List.filter(fun e -> e > xs.Head)
match xs with
| [] -> []
| _ -> qsort(smaller)#[xs.Head]#qsort(larger)
Is there a way in f# to write it more like Haskell:
qsort :: [Int] -> [Int]
qsort [] = []
qsort (x:xs) =
qsort smaller ++ [x] ++ qsort larger
where
smaller = [a | a <- xs, a <= x]
larger = [b | b <- xs, b >= x]
I know the f# algorithm is missing a <= and >=. The question is more about syntax/readibility.
Thanks.
This is the most 'Haskellian' way I can think of, the only thing missing is being able to declare smaller/larger as a 'where' clause:
let rec qsort:int list -> int list = function
| [] -> []
| x::xs -> let smaller = [for a in xs do if a<=x then yield a]
let larger = [for b in xs do if b>x then yield b]
qsort smaller # [x] # qsort larger
I know it's not part of your question, but I'd use List.partition to split the list in smaller/larger in a single pass:
let rec qsort = function
| [] -> []
| x::xs -> let smaller,larger = List.partition (fun y -> y<=x) xs
qsort smaller # [x] # qsort larger
You want your second match clause to be x :: xs, and to use the # (append) operator where your Haskell example uses ++:
let rec qsort xs =
match xs with
| [] -> []
| x :: xs ->
let smaller = qsort (xs |> List.filter(fun e -> e <= x))
let larger = qsort (xs |> List.filter(fun e -> e > x))
smaller # [x] # larger
It's not quite the same as the Haskell definition by cases syntax, but hopefully similar enough for you!
...Or you could make a tail recursive qsort by using CPS:
let qSort lst =
let rec qs l cont =
match l with
| [] -> cont []
| (x::xs) -> qs (List.filter (fun e -> e <= x) xs) (fun smaller ->
qs (List.filter (fun e -> e > x) xs) (fun larger ->
smaller # (x :: larger) |> cont))
qs lst id
This seems to be as concise as it can get (combining the ideas from other answers, and using currying for operators):
let rec qsort = function
| [] -> []
| (x:int) :: xs ->
let smaller = List.filter ((>=) x) xs
let larger = List.filter ((<) x) xs
qsort smaller # [x] # qsort larger
haskell 'where' syntax, which lets you use the name of a function before its definition, kind of maps to f# 'let rec ... and'
let qsort xs =
let rec sort xs =
match ls with
|[] -> ....
|h::t -> (smaller t) # h # (larger t)
and smaller ls = //the 'and' lets you define the
// function after where it is used,
// like with 'where' in haskell
... define smaller in terms of sort
and larger ls =
... same
sort xs
let rec QuickSort l =
match l with
| [] -> []
| _ -> QuickSort([for e in l do if e < (List.head l) then yield e]) #[(List.head l)]# QuickSort([for e in l do if e > (List.head l) then yield e])
Don't forget that List has a partition method, so
let rec quicksort ls =
match ls with
| [] -> []
| h :: t -> let fore, aft = List.partition (fun i -> i < h) t
(quicksort fore) # (h :: quicksort aft)
I had done some analysis of sorting algorithms in F# a few years ago in a very imperative style; I was trying to beat the .NET stock implementation, and managed to do so here. Went to make the following reply to myself today, but FPish won't let me create an account. Argh! Gotta make my post somewhere, and here's as good as anywhere, lol...
While reading "Learn You a Haskell For Great Good" yesterday, the author set up an example for implementing quicksort. The description was quite clear and even before I got to the sample code, an elegant recursive solution (in Haskell) popped into my head. Guess I had never really had an intuitive feel for how quicksort does its thing, because the trivial solution is quite easy, if not very efficient.
Here is my version in F#:
let rec quicksort = function
| [] -> []
| pivot :: xs ->
(left pivot xs) # pivot :: (right pivot xs)
and left pivot xs = quicksort [ for x in xs do if x <= pivot then yield x ]
and right pivot xs = quicksort [ for x in xs do if x > pivot then yield x ]
And, the equivalent Haskell (I like this one... clean!):
quicksort :: Ord a => [a] -> [a]
quicksort [] = []
quicksort (pivot : xs) =
left ++ pivot : right
where
left = quicksort [ x | x <- xs, x <= pivot ]
right = quicksort [ x | x <- xs, x > pivot ]
For grins, here's another F# version (mostly tail-recursive) that's about 2x the speed of the trivial version. Haven't bothered to time this against my original post, though, so no idea how it stacks up to the mutable version in my OP on FPish.net (FSHub) from a few years ago...
let rec quicksort' xs =
let rec aux pivot left right = function
| [] -> (quicksort' left) # pivot :: (quicksort' right)
| x :: xs ->
if x <= pivot then
aux pivot (x :: left) right xs
else
aux pivot left (x::right) xs
match xs with
| [] -> []
| x :: xs -> aux x [] [] xs

Resources