Ocaml:如何将音符转换为和弦



我想在ocaml中从一个音符和一个列表创建一个和弦。

结构:

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

和列表

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

非常感谢你的回答。Marie

大问题应该用小步骤解决。首先,让我们创建一个函数transpose_objet,该函数将采用具有单个转置(即移位)的单个对象,并返回一个新对象,该对象按指定的移位按音高转置。

(** [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)

接下来,让我们尝试创建一个由三个换位组成的和弦。所以我们取一个三元组和一个物体,并平行播放(我认为这就是和弦的含义)。我们将此函数命名为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]

有了这些方便的函数,我们可以处理组成三元组的列表。让我们写一个函数chords_of_transpositions,所以我们想取一个音乐对象和转置列表,并从每个转置中创建一个和弦。我们希望它仍然是一个音乐对象,所以我们使用构造函数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)

作为一个练习,我建议您重写函数chord_of_composition,不要出现难看的重复(提示,使用List.map)。

作为第二个练习,尝试从transpose_objet函数中删除代码重复。您注意到ParallelSequence子句的模式是相同的吗。

作为第三个练习,试着重写你的代码,这样你的换位列表就不是由三元组组成的,而是由n-let组成的,就像这样:

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

其中空列表代表静音。

回答一个新问题

问题

我试试这个

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

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

和你的主张

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

和测试

设test=脊索化seq1换位;;

但顶部Ocaml返回

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 . 

如何解决?

答案

首先,我想指出的是,我们正开始努力推动SO。它是一个问答网站,而不是一个论坛。我为你做了一些工作,但我看不出你在尽力尽自己的职责。我来这里不是为了做你的家庭作业,而是为了帮助你解决关于OCaml和编程的一般问题。我的建议是从一本关于OCaml的好教材开始,先学习。只是尝试随机复制粘贴代码,直到编译,这不是一个好主意。现在,回到你的问题上来。

首先,您可以使用一种更方便的表示法:[1;2;3],而不是像1 :: 2 :: 3 :: []那样以如此粗糙的方式构建列表。这样你的序列就可以用以下方式重写:

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

接下来,你的功能

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

指的是一些未绑定的符号CCD_ 12。如果您想在函数自身内部调用函数,则需要使其递归,即将rec添加到let表达式中:

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

我认为,您已经两次将此函数加速推送到OCaml顶层,因此您实际上已经进行了以下int定义。

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

但是,你真正想做的是,不调用函数cordify,而是调用函数chord_of_transposition,它将根据一个特定的换位实例来转换objet_musical,类似于这样的:

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

因此,我们得出了一个定义,等于函数chords_of_transpositions的定义,我之前已经提供了。

相关内容

  • 没有找到相关文章

最新更新