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.
Related
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
This question already has answers here:
Merge sort for f sharp
(2 answers)
Closed 5 years ago.
The code underneath is the code for mergesort in f# and I have to rewrite it, so it uses pattern matching.
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)
So far I've gotten is to here:
let rec msort (vs: int list) =
let sz = List.length xs
match xs with
| List.length < 2 -> vs
| _ ->
let n = sz / 2
let ys = xs.[0..n-1]
let zs = xs.[n..sz-1]
in merge (msort ys) (msort zs)
I can't seem to figure out a better way. Is there anyone who can help me on my way?
I would probably do it like this:
let rec msort (values: int list) =
let n = values.Length / 2
if n = 0
then values
else let rec merge (xs: int list) (ys: int list) =
match (xs, ys) with
| ([], ys) -> ys
| (xs, []) -> xs
| (x :: xs1, y :: ys1) ->
if x < y
then x :: merge xs1 ys
else y :: merge xs ys1
let (first, second) = values |> List.splitAt n
merge (msort first) (msort second)
Pattern matching isn't too useful on the initial logic (length of the list, early exits for length 0 and 1), but I think it makes it more readable when matching the cases for the sub-lists after the split. Even so, there's only one if/then in the msort portion and it could be replaced with a pattern match if you really wanted to:
let rec msort (values: int list) =
match values.Length / 2 with
| 0 -> values
| n ->
let rec merge (xs: int list) (ys: int list) =
match (xs, ys) with
| ([], ys) -> ys
| (xs, []) -> xs
| (x :: xs1, y :: ys1) ->
if x < y
then x :: merge xs1 ys
else y :: merge xs ys1
let (first, second) = values |> List.splitAt n
merge (msort first) (msort second)
This leaves only the if/then for x<y in the merge implementation, and I wouldn't change that.
Almost the same, but I propose a custom split:
let split2 (li: int list) =
let n = (List.length li) / 2
let rec looprec (len: int) (l1: int list) (l2: int list) =
if len > 0 then
match l1 with
| x::tail -> looprec (len-1) tail (x::l2)
| _ -> (List.rev l2, l1)
else
(List.rev l2, l1)
in looprec n li []
let rec merge (l1: int list) (l2: int list) =
match (l1,l2) with
| (x,[]) -> x
| ([],y) -> y
| (x::tx,y::ty) ->
if x <= y
then x::merge tx l2
else y::merge l1 ty
let rec msort (li: int list) =
match li with
| [] -> []
| [x] -> [x]
| _ -> let (l1,l2) = split2 li
in merge (msort l1) (msort l2)
let d= msort [3;20;12]
printfn "%A" d
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)
For cartesian production there is a good enough function - sequence which defined like that:
let rec sequence = function
| [] -> Seq.singleton []
| (l::ls) -> seq { for x in l do for xs in sequence ls do yield (x::xs) }
but look at its result:
sequence [[1..2];[1..10000]] |> Seq.skip 1000 ;;
val it : seq = seq [[1; 1001]; [1; 1002]; [1; 1003]; [1; 1004]; ...]
As we can see the first "coordinate" of the product alters very slowly and it will change the value when the second list is ended.
I wrote my own sequence as following (comments below):
/// Sum of all producted indeces = n
let rec hyper'plane'indices indexsum maxlengths =
match maxlengths with
| [x] -> if indexsum < x then [[indexsum]] else []
| (i::is) -> [for x in [0 .. min indexsum (i-1)] do for xs in hyper'plane'indices (indexsum-x) is do yield (x::xs)]
| [] -> [[]]
let finite'sequence = function
| [] -> Seq.singleton []
| ns ->
let ars = [ for n in ns -> Seq.toArray n ]
let length'list = List.map Array.length ars
let nmax = List.max length'list
seq {
for n in [0 .. nmax] do
for ixs in hyper'plane'indices n length'list do
yield (List.map2 (fun (a:'a[]) i -> a.[i]) ars ixs)
}
The key idea is to look at (two) lists as at (two) orthogonal dimensions where every element marked by its index in the list. So we can enumerate all elements by enumerating every element in every section of cartesian product by hyper plane (in 2D case this is a line). In another words imagine excel's sheet where first column contains values from [1;1] to [1;10000] and second - from [2;1] to [2;10000]. And "hyper plane" with number 1 is the line that connects cell A2 and cell B1. For the our example
hyper'plane'indices 0 [2;10000];; val it : int list list = [[0; 0]]
hyper'plane'indices 1 [2;10000];; val it : int list list = [[0; 1]; [1; 0]]
hyper'plane'indices 2 [2;10000];; val it : int list list = [[0; 2]; [1; 1]]
hyper'plane'indices 3 [2;10000];; val it : int list list = [[0; 3]; [1; 2]]
hyper'plane'indices 4 [2;10000];; val it : int list list = [[0; 4]; [1; 3]]
Well if we have indeces and arrays that we are producing from the given lists than we can now define sequence as {all elements in plane 0; than all elements in plane 1 ... and so on } and get more volatile function than original sequence.
But finite'sequence turned out very gluttonous function. And now the question. How I can improve it?
With best wishes, Alexander. (and sorry for poor English)
Can you explain what exactly is the problem - time or space complexity or performance? Do you have a specific benchmark in mind? I am not sure how to improve on the time complexity here, but I edited your code a bit to remove the intermediate lists, which might help a bit with memory allocation behavior.
Do not do this:
for n in [0 .. nmax] do
Do this instead:
for n in 0 .. nmax do
Here is the code:
let rec hyper'plane'indices indexsum maxlengths =
match maxlengths with
| [] -> Seq.singleton []
| [x] -> if indexsum < x then Seq.singleton [indexsum] else Seq.empty
| i :: is ->
seq {
for x in 0 .. min indexsum (i - 1) do
for xs in hyper'plane'indices (indexsum - x) is do
yield x :: xs
}
let finite'sequence xs =
match xs with
| [] -> Seq.singleton []
| ns ->
let ars = [ for n in ns -> Seq.toArray n ]
let length'list = List.map Array.length ars
let nmax = List.max length'list
seq {
for n in 0 .. nmax do
for ixs in hyper'plane'indices n length'list do
yield List.map2 Array.get ars ixs
}
Does this fare any better? Beautiful problem by the way.
UPDATE: Perhaps you are more interested to mix the sequences fairly than in maintaining the exact formula in your algorithm. Here is a Haskell code that mixes a finite number of possibly infinite sequences fairly, where fairness means that for every input element there is a finite prefix of the output sequence that contains it. You mention in the comment that you have a 2D incremental solution that is hard to generalize to N dimensions, and the Haskell code does exactly that:
merge :: [a] -> [a] -> [a]
merge [] y = y
merge x [] = x
merge (x:xs) (y:ys) = x : y : merge xs ys
prod :: (a -> b -> c) -> [a] -> [b] -> [c]
prod _ [] _ = []
prod _ _ [] = []
prod f (x:xs) (y:ys) = f x y : a `merge` b `merge` prod f xs ys where
a = [f x y | x <- xs]
b = [f x y | y <- ys]
prodN :: [[a]] -> [[a]]
prodN [] = [[]]
prodN (x:xs) = prod (:) x (prodN xs)
I have not ported this to F# yet - it requires some thought as sequences do not match to head/tail very well.
UPDATE 2:
A fairly mechanical translation to F# follows.
type Node<'T> =
| Nil
| Cons of 'T * Stream<'T>
and Stream<'T> = Lazy<Node<'T>>
let ( !! ) (x: Lazy<'T>) = x.Value
let ( !^ ) x = Lazy.CreateFromValue(x)
let rec merge (xs: Stream<'T>) (ys: Stream<'T>) : Stream<'T> =
lazy
match !!xs, !!ys with
| Nil, r | r, Nil -> r
| Cons (x, xs), Cons (y, ys) -> Cons (x, !^ (Cons (y, merge xs ys)))
let rec map (f: 'T1 -> 'T2) (xs: Stream<'T1>) : Stream<'T2> =
lazy
match !!xs with
| Nil -> Nil
| Cons (x, xs) -> Cons (f x, map f xs)
let ( ++ ) = merge
let rec prod f xs ys =
lazy
match !!xs, !!ys with
| Nil, _ | _, Nil -> Nil
| Cons (x, xs), Cons (y, ys) ->
let a = map (fun x -> f x y) xs
let b = map (fun y -> f x y) ys
Cons (f x y, a ++ b ++ prod f xs ys)
let ofSeq (s: seq<'T>) =
lazy
let e = s.GetEnumerator()
let rec loop () =
lazy
if e.MoveNext()
then Cons (e.Current, loop ())
else e.Dispose(); Nil
!! (loop ())
let toSeq stream =
stream
|> Seq.unfold (fun stream ->
match !!stream with
| Nil -> None
| Cons (x, xs) -> Some (x, xs))
let empty<'T> : Stream<'T> = !^ Nil
let cons x xs = !^ (Cons (x, xs))
let singleton x = cons x empty
let rec prodN (xs: Stream<Stream<'T>>) : Stream<Stream<'T>> =
match !!xs with
| Nil -> singleton empty
| Cons (x, xs) -> prod cons x (prodN xs)
let test () =
ofSeq [
ofSeq [1; 2; 3]
ofSeq [4; 5; 6]
ofSeq [7; 8; 9]
]
|> prodN
|> toSeq
|> Seq.iter (fun xs ->
toSeq xs
|> Seq.map string
|> String.concat ", "
|> stdout.WriteLine)
Using the following continuation monad:
type ContinuationMonad() =
member this.Bind (m, f) = fun c -> m (fun a -> f a c)
member this.Return x = fun k -> k x
let cont = ContinuationMonad()
I fail to see why the following gives me a stack overflow:
let map f xs =
let rec map xs =
cont {
match xs with
| [] -> return []
| x :: xs ->
let! xs = map xs
return f x :: xs
}
map xs id;;
let q = [1..100000] |> map ((+) 1)
While the following doesn't:
let map f xs =
let rec map xs =
cont {
match xs with
| [] -> return []
| x :: xs ->
let! v = fun g -> g(f x)
let! xs = map xs
return v :: xs
}
map xs id;;
let q = [1..100000] |> map ((+) 1)
To fix your example, add this method to your definition of the monad:
member this.Delay(mk) = fun c -> mk () c
Apparently the part that overflows is the destruction of the large input list in the recursive call of map. Delaying it solves the problem.
Note that your second version puts the recursive call to map behind another let! which desugars to Bind and an extra lambda, in effect delaying the recursive call to map.
I had to pursue a few false trails before reaching this conclusion. What helped was observing that StackOverflow is thrown by OCaml as well (albeit at a higher N) unless the recursive call is delayed. While F# TCO has some quirks, OCaml is more proven, so this convinced me that the problem is indeed with the code and not the compiler:
let cReturn x = fun k -> k x
let cBind m f = fun c -> m (fun a -> f a c)
let map f xs =
(* inner map loop overflows trying to pattern-match long lists *)
let rec map xs =
match xs with
| [] -> cReturn []
| x :: xs ->
cBind (map xs) (fun xs -> cReturn (f x :: xs)) in
map xs (fun x -> x)
let map_fixed f xs =
(* works without overflowing by delaying the recursive call *)
let rec map xs =
match xs with
| [] -> cReturn []
| x :: xs ->
cBind (fun c -> map xs c) (fun xs -> cReturn (f x :: xs)) in
map xs (fun x -> x)
let map_fused f xs =
(* manually fused version avoids the problem by tail-calling `map` *)
let rec map xs k =
match xs with
| [] -> k []
| x :: xs ->
map xs (fun xs -> k (f x :: xs)) in
map xs (fun x -> x)
The F# compiler is sometimes not very clever - in the first case it computes map xs then f x and then joins them, so map xs is not in a tail position. In the second case, it can reorder the map xs to be in tail position easily.