2

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.

Community
  • 1
  • 1
happyD
  • 146
  • 9

1 Answers1

4

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 -> …
Gilles 'SO- stop being evil'
  • 104,111
  • 38
  • 209
  • 254
  • Thanks Gilles. If I were to do it in the way x::y::mux(xs,ys) instead of x :: mux ys xt, what would it look like? This is for pedagogical reasons because I'm struggling to understand the syntax. – happyD Feb 03 '17 at 20:29
  • Gilles, I am doing my best to try and fill the gaps, but I am really struggling. I apologize to be pestering. With the nest function construct for instance, what would I put in place of the ellipses? Would I put [] instead of the first ellipses and ys instead of the second, xs instead of the 3rd and x::y::mux(xt,yt) in the 4th? – happyD Feb 03 '17 at 22:27
  • 1
    @happyD Put the code that you want to return from the function. For example `match xs, ys with [], _ -> ys | _, [] -> xs | x::xt, y::yt -> x :: y :: mux xt yt` (the pattern `_` means “anything”, just like in Haskell). – Gilles 'SO- stop being evil' Feb 03 '17 at 22:36
  • I'm starting to get it. I put in this and it also worked. It is not elegant but it is for pedagogy. let rec mux2 = function | [] -> (function [] -> [] | y::yt -> y::yt) | x::xt -> (function [] -> x::xt | y::yt -> x::y::mux2 xt yt) – happyD Feb 03 '17 at 23:47