Pattern matching on complex ocaml data structures

I'm completely new to OCaml so I'm having trouble with the basics. For my program, I need to match the nucleotide with the complement (G → C, C → G, A → T, T → A) to find the second half of the double helix. The general idea is that DNA is made up of 2 additional helices, each of which is a sequence of nucleotides. I am currently trying to calculate the second half of the double helix.

So far, I have presented enumerated nucleotides, and I have presented DNA with a nucleotide list that matches one helix.

type nucleotide = 
| G 
| C 
| A 
| T

type helix = nucleotide list

let rec complementary_helix (x:helix): helix =
| [G] -> [C]
| [C] -> [G]
| [A] -> [T]
| [T] -> [A]
end

      

I know I am missing something here, but I don’t know how. Can anyone point me in the right direction?

+3


source to share


1 answer


Mostly just missing List.map

:

let complement = function
| G -> C
| C -> G
| A -> T
| T -> A

let complementary_helix (x: helix) : helix =
    List.map complement x

      

(Why not specify types. OCaml will infer types. Nice style to specify for documentation, but perhaps not if obvious.)

Edit

OK, I think this is a homework problem where you have to use recursion to solve the problem.

The way to think about recursion is that you want to solve a small part of the problem, which gives you a smaller problem to solve. You pass on the lesser problem to yourself (before or after you solve your little piece). You also need to know when the problem has become so small that there is nothing else to do.



In your case, a small piece would have to translate one nucleotide in its complement. You are doing this semi-OK (you have lists where you would really like to work on single nucleotides). But you are not passing the rest of the problem to yourself to solve recursively. You also don't check if the problem is so small that there is nothing to do.

For functions in lists, about 99% of the time, you will reduce the task by splitting the list into a head (one item) and a tail (a list that is less than one at a time). This will work for you here.

Edit 2

As an example of what list recursion looks like, here is a function that concatenates all integers in a list:

let rec sum l =
    match l with
    | [] -> 0
    | head :: tail -> head + sum tail

      

It has all the parts I have described. match

is used both to identify a trivial problem (when the list is empty) and to split the list into head and tail. Assuming you have the sum for the tail (which you can get recursively), the answer is pretty obvious. You just need to add a head for that amount. You just have to ask yourself (almost always): If I had an answer to the tail of a list, what would I need to do to combine it with the head?

+6


source







All Articles