Cartesian product two lists [duplicate] - f#

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
F# - cross product of two lists
Projecting a list of lists efficiently in F#
I have a function that takes two integer lists and returns a single list with all the cartesian products. I think i have the correct idea but not the right implementation. Can I get some pointers?
let rec cartesian = function
| ([],[]) -> []
| (xs,[]) -> []
| ([],ys) -> []
| (x::xs,ys) -> List.map(fun y -> (x,y)::[]) cartesian (xs,ys)

This is a quick fix:
let rec cartesian = function
| ([],[]) -> []
| (xs,[]) -> []
| ([],ys) -> []
| (x::xs, ys) -> (List.map(fun y -> x,y) ys) # (cartesian (xs,ys))
The idea is that with each element x, you generate a list [(x, y1); (x, y2); ...; (x, yn)] and concatenate those lists altogether.
In your function, the first pattern matching case is redundant. And the arguments are more convenient to be in the curried form. The function could look like this:
let rec cartesian xs ys =
match xs, ys with
| _, [] -> []
| [], _ -> []
| x::xs', _ -> (List.map (fun y -> x, y) ys) # (cartesian xs' ys)
Once you understand the idea, you can see that the high-order function List.collect perfectly matches the task:
let cartesian xs ys =
xs |> List.collect (fun x -> ys |> List.map (fun y -> x, y))

Related

F# Finding occurrences of value in list

I'm quite a newbie at F# and want to find how many times a value x has occurred in a list ys
So for example multiplicity (2, [1;2;3;4;2]) returns 2. The code I've written below returns 4 on the above example. What am I missing?
let rec multiplicity (x, ys) =
match ys with
| [] -> 0
| y::tail when x=y -> x + multiplicity(x, tail)
| y::tail -> multiplicity(x, tail)
If you're not writing this as a recursive function as a learning exercise, it's probably more idiomatic to use the built-in collection functions:
[1;2;3;4;2] |> Seq.filter ((=) 2) |> Seq.length
[1;2;3;4;2] |> List.sumBy (fun x -> if x = 2 then 1 else 0)
Alright, this is a good example of why it's always a good idea to write down a problem/question.
I figured out, I should do this instead:
let rec multiplicity (x, ys) =
match ys with
| [] -> 0
| y::tail when x=y -> 1 + multiplicity(x, tail)
| y::tail -> multiplicity(x, tail)
It should be 1 and not x, which is added to the recursive call, doh.
I find it's a good idea to replace recursion with fold, so here is another version:
let xs = [1;2;3;4;2]
(0,xs) ||> List.fold (fun acc elem -> match elem with
| 2 -> acc + 1
| _ -> acc)
You can also use countBy, which will return a list of tuples with true and false.
xs |> List.countBy (fun x -> x = 2)

Translate merge function from Haskell to F#

I have this function in haskell which I would like to code in F# using native syntax and not the array functions such as map2.
Haskell:
merge [] ys = ys
merge (x:xs) ys = x:merge ys xs
This code merges two lists index-wise like this:
INPUT: [1,2,3,4,5] [11,12,13,14]
OUTPUT: [1,11,2,12,3,13,4,14,5]
I tried doing it in F# and got this but it of course doesn't compile:
let rec mux x y = function
| [] -> []
| x::xs y::ys -> x::y::mux(xs,ys)
I am really struggling to work with two arrays in the pattern matching, thanks for any help you can give.
The Haskell function doesn't actually match on the two parameters. It only matches on the first parameter and takes the second parameter as is.
In F#, you can match on the first argument, and return a function that processes the second argument:
let rec mux = function
| [] -> (function ys -> ys)
| x::xt -> (function ys -> x :: mux ys xt)
But I find it clearer (and I think it's more efficient — at least it is in OCaml) to take in all the arguments at once, then analyze the argument you need to discriminate on:
let rec mux xs ys =
match xs with
| [] -> ys
| x::xt -> x :: mux ys xt
If you wanted to match on both variables, there would be several solutions. You could nest function constructs:
let rec mux = function
| [] -> (function [] -> … | y::yt -> …)
| x::xt -> (function [] -> … | y::yt -> …)
But here again I prefer nesting match constructs:
let rec mux xs ys =
match xs with
| [] -> (match ys with
| [] -> …
| y::yt -> …)
| x::xt -> (match ys with
| [] -> …
| y::yt -> …)
Alternatively, it's often nicer to match on the pair of inputs; it depends how coupled the two inputs are.
let rec mux xs ys =
match xs, ys with
| [], [] -> …
| [], y::yt -> …
| x::xt, [] -> …
| x::xt, y::yt -> …

F# function - expected type differs from actual

I have been trying to write a curried function "multvec" which uses u=(u1, u2, ..., un) and v=(v1, v2, ..., vn) and outputs u1*v1 + u2*v2 + ... + un*vn. I think I have the logic mostly correct (at least it would be in other languages...) but I keep getting an:
stdin(11,57): error FS0001: This expression was expected to have type
'a list
but here has type
'c list * 'd list -> 'b list
The code is below: The problem is clearly in the call to product in the last line. However, I was under the impression that the base case ( x * y )::[ ] would just product an 'a list, instead of what it actually produces.
let rec multvec xs ys = function
| [ ], [ ] -> failwith "Both lists cannot be empty"
| x::[ ], y::[ ] -> ( x * y )::[ ]
| x::xs, y::ys -> let product = multvec xs ys
( x * y ) + ( List.reduce (+) product )
Any clarity on this error would be greatly appreciated! Thank you in advance.
Your code honestly has more wrong with it than right: ;-]
It's not tail-recursive
Use of function when xs and ys are separate parameters
Incomplete pattern match
Having one branch evaluate to a list and another evaluate to a scalar
All products are manually added together except for the last, which has a List.reduce run over a single-element list – slightly backwards ;-]
Here's a sensible implementation that fixes all of the above:
let inline multvec xs ys = List.map2 (*) xs ys |> List.sum
Note that if performance is a primary concern then it may be worth avoiding List.sum, as it uses checked arithmetic. One could do the following instead if using unchecked arithmetic is okay:
let inline multvec xs ys = List.map2 (*) xs ys |> List.reduce (+)
If you really want to do this manually, here's one approach:
let inline multvec xs ys =
let rec impl acc = function
| [], [] -> acc
| x::xs', y::ys' -> impl (x * y + acc) (xs', ys')
| _ -> failwith "lists must be of equal length"
impl LanguagePrimitives.GenericZero (xs, ys)
To add to ildjarn's answer, you can fuse map2 and reduce into a single function call using fold2 to compute the dot product ("multvec") of two vectors:
let inline dot xs ys =
let zero = LanguagePrimitives.GenericZero
List.fold2 (fun acc x y -> acc + x * y) zero xs ys
This would save you from creating an unnecessary temporary list.

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