1

I would like to create a chord from a note and a list in ocaml.

the structure :

type objet_musical =
    | Note of (int * int * int)
    | Silence of int
    | Sequence of objet_musical list
    | Parallel of objet_musical list

and the list

let transposition = [(0,4,7);(0,3,7);(0,4,8);(0,3,6)];;

Many thanks for your answer. Marie

Matthieu Brucher
  • 21,634
  • 7
  • 38
  • 62
Marie
  • 21
  • 3

1 Answers1

0

Big problems should be tackled in a small steps. First let's create a function transpose_objet that will take a single object with a single transposition, i.e., a shift, and returns a new object, that is transposed in a pitch by the specified shift.

(** [transpose_objet obj shift] takes a musical object [obj] and
    transposes it pitch to a value [shift] *)
let rec transpose_objet obj shift : objet_musical = match obj with
  | Note (h,v,d) -> Note (h + shift, v, d)
  | Silence t -> Silence t
  | Sequence objs ->
    Sequence (List.map (fun obj -> transpose_objet obj shift) objs)
  | Parallel objs ->
    Parallel (List.map (fun obj -> transpose_objet obj shift) objs)

Next, let's try to create a chord of three transpositions. So we take a triplet and an object and play it in a parallel (I think that is what chord stands for). We will name this function chord_of_transposition.

(** [chord_of_transposition obj tlist] takes a musical [obj] and a triplet,
    where every element of triplet is a number to which the pitch
    should be transposed, and creates a chord *)
let chord_of_transposition obj (t1,t2,t3) : objet_musical =
      Parallel [transpose_objet obj t1;
                transpose_objet obj t2;
                transpose_objet obj t3]

With this handy functions, we can tackle a list of composition triplets. Let's write a function chords_of_transpositions So we would like to take a musical object and list of transpositions, and create a chord from each transposition. And we would like it to be still a musical object, so we create from a resulting list an object using constructor Sequence.

(** [chords_of_transpositions obj transpositions] takes a list of
    triplets, where each element of triplet is value by which a
    musical object should be shifted and creates a sequence of musical
    objects that will play a chords from each transposition.  *)
let chords_of_transpositions obj ts : objet_musical =
  Sequence (List.map (chord_of_transposition obj) ts)

As an exercise, I would suggest you, to rewrite function chord_of_composition without the ugly repetition (hint, use List.map).

As a second exercise, try to remove code repetitions from transpose_objet function. Did you noticed that patterns for Parallel and Sequence clause are the same.

As a third exercise, try to rewrite your code, so that your transposition list consists not from triplets, but from n-plets, like this:

let transposition = [[0;4;7];[0;3;7]; [0;8]; []; [0;3;6]]

where empty list stands for silencing.

Answer to a new question

Question

I try this

let seq1= Sequence((Note(60,100,1000)):: (Note (64,100,500)):: (Note (62,100,500)):: (Silence(1000)):: (Note (67,100,1000)):: []) 

and

let transposition= [(0,4,7);(0,3,7);(0,4,8);(0,3,6)];; 

and your proposition

let chordify om tp : objet_musical= Sequence (List.map (chordify om)tp);; 

and the test

let test= chordify seq1 transposition;;

but top Ocaml return

Error: This expression has type (int * int * int) list but an expression was expected   of type int list list Type int * int * int is not compatible with type int list . 

How to solve it?

Answer

First of all, I would like to note, that we are starting to push to hard on SO. It is a question/answer site, not a forum. I've made some work for you, but I do not see, that you're trying to do your part. I'm here not to do your homework, but to help you with general questions on OCaml and programming. My advice would be start from a good textbook about OCaml and learn it first. Just trying to randomly copy-paste code, until compiles is not a good idea. Now, back to your question.

First of all, instead of building list in a such crude way like 1 :: 2 :: 3 :: [] you can use a more conviniet notation: [1;2;3]. So that your sequence can be rewritten in a following way:

let seq1 = Sequence [
    Note (60,100,1000);
    Note (64,100,500);
    Note (62,100,500);
    Silence (1000);
    Note (67,100,1000)
]

Next, your function

let chordify om tp : objet_musical =
  Sequence (List.map (chordify om) tp)

refers to some unbound symbol chordify. If you want to call a function inside its own body, you need to make it recursive, i.e., to add rec to the let expression:

let rec chordify om tp : objet_musical =
  Sequence (List.map (chordify om) tp)

I think, that you have accedantaly pushed this function twice to OCaml top-level, so that effectively you've made the followint definition.

let chordify om tp : objet_musical =
  Sequence (List.map (chordify om) tp)

let chordify om tp : objet_musical =
  Sequence (List.map (chordify om) tp)

But instead, what do you really want to do, is to not to call function cordify but to call function chord_of_transposition that will transform an objet_musical accroding with a particular instance of transposition, something like this:

let chordify om tp : objet_musical =
  Sequence (List.map (chord_of_transposition om) tp)

So we come out with a defintion equal to the definition of a function chords_of_transpositions, that I have provided previously.

ivg
  • 34,431
  • 2
  • 35
  • 63
  • I have to associate objet_musical with the transposition list. – Marie Oct 12 '14 at 14:40
  • I have to associate objet_musical with the transposition list. For example if note do=60 and note*list => chords (60,64,67). – Marie Oct 12 '14 at 14:43
  • Ok, now I have two questions: (1) what is the triplet (`int * int * `int) in a Note constructor? Does it correspond in a some way to pitch, octave, duration or, maybe, volume? (2) What is the meaning of triplets in a transposition list? Do you need to transpose each `object_musical` in three different transposition? – ivg Oct 12 '14 at 14:59
  • triplet means (height, volume, duration). Yes, I would like to transpose each object_musical in the list transposition. – Marie Oct 12 '14 at 15:13
  • height is the pitch? And I don't understand the second part: You have a list of `objet_musical` and you have a list of transpositions triplets, where each triplet stands for a separate pitch transposition? And you want to apply one to another, somehow, so that each `objet_musical` will be triplicated? – ivg Oct 12 '14 at 15:18
  • I am very sorry to be so unclear. I would like to write a method which takes as argument a note and a transposition list. each triplet from the list must apply to the note and return a chord. Do=60, Re=62, Mi=64, Fa=65, sol=67, la=69;si=70. If I apply the transposition list a must return do=60,64,67... I add the note value to the value list. – Marie Oct 12 '14 at 15:29
  • I think that I've got it. See the updated answer. If you have questions, don't be afraid to ask them. – ivg Oct 12 '14 at 16:07
  • I do the transpose function = add a value to a pitch. But how to do the same with a list ? – Marie Oct 12 '14 at 16:26
  • if you have transformation of an object, and you need to apply it to a sequence of objects, then this operation is called `map`. And it is provided for all collections, including a `list` (in a latter case it is called `List.map`). I would suggest you to carefully walkthrough my answer. So, that you can see, that the last function `chords_of_transpositions` is an answer to your question, i.e., it applies an object to a list of transposition triplets. Try to load them into OCaml toplevel, and play with them. – ivg Oct 12 '14 at 16:33
  • I try this let seq1= Sequence((Note(60,100,1000)):: (Note (64,100,500)):: (Note (62,100,500)):: (Silence(1000)):: (Note (67,100,1000)):: []) and let transposition= [(0,4,7);(0,3,7);(0,4,8);(0,3,6)];; and your proposition let chordify om tp : objet_musical= Sequence (List.map (chordify om)tp);; and the test let test= chordify seq1 transposition;; but top Ocaml return Error: This expression has type (int * int * int) list but an expression was expected of type int list list Type int * int * int is not compatible with type int list . How to solve it? – Marie Oct 12 '14 at 16:52
  • I am very sorry for all. I just want understand how Ocaml works in a particular situation. I have fully appreciated your comments. Thanks for your time. – Marie Oct 12 '14 at 21:25