了解Ocaml的结构

时间:2019-03-17 22:14:10

标签: ocaml

当我浏览网站时: http://www.cs.princeton.edu/courses/archive/fall14/cos326/sec/03/precept03_sol.ml

根据Ocaml的结构,我有一个问题。具体来说,我对代码有疑问:

let rec reduce (f:'a -> 'b -> 'b) (u:'b) (xs:'a list) : 'b =
    match xs with
    | [] -> u
    | hd::tl -> f hd (reduce f u tl);;

f hd在最后一行做什么? (我知道reduce f u tl再次调用了函数本身。)

我的第二个问题是如何使用一个函数在Ocaml中实现另一个函数。对于代码:

let times_x (x: int) (lst: int list) : int list =  
  map (fun y -> y*x) lst

fun y -> y*x的作用是什么? lst在代码末尾做什么?

谢谢您的帮助!

1 个答案:

答案 0 :(得分:1)

The code that has been provided is a reduce function that takes three parameters - a function that maps inputs of type 'a and 'b to an output of type 'b, a value of type 'b, and as list of elements of type 'a.

For example, the length example from the lecture:

let length (lst: int list) : int = 
  reduce (fun _ len -> len + 1) 0 lst

The first parameter to reduce is a function that, when given two parameters, discards the first one and returns the second parameter incremented by one. The second is a value (0) to be used as an accumulator. The third is a list to find the length of.

The behavior of this recursive reduce function is to return the second parameter (an accumulator as used in the length example) once the provided list is empty, and otherwise run the provided function using the head of the list and the recursed value.

Once again going to the length example, say we give it a list with a single element [1].

Our call to length becomes reduce (fun _ len -> len + 1) 0 [1]

Recall reduce:

let rec reduce (f:'a -> 'b -> 'b) (u:'b) (xs:'a list) : 'b =
    match xs with
    | [] -> u
    | hd::tl -> f hd (reduce f u tl);;

First, we match [1] against [], which fails. Since it is a non-empty list, we run f hd (reduce f u tl)

Recall that f is the parameter that length provided: fun _ len -> len + 1

Therefore, we effectively run the following:

(fun _ len -> len + 1) 1 (reduce (fun _ len -> len + 1) 0 [])

In this case, the length function discards the first parameter since the values in the list are not necessary to know the length of the list.

The recursive portion will match against [] and return the value of u at the time, which is 0.

Therefore, one level up, (fun _ len -> len + 1) 1 (reduce (fun _ len -> len + 1) 0 []) becomes (fun _ len -> len + 1) 1 0 and returns 0 + 1, simplifying to our expected value 1, which represents the length of the list.


Now, to your second question, in regards to times_x. This performs a mapping. For example, we can map [1;2;3;4;5] to [3;6;9;12;15] with a mapping fun x -> x * 3.

Here times_x is defined as follows:

let times_x (x: int) (lst: int list) : int list =
  map (fun y -> y*x) lst

times_x takes an integer and a list. Using the above example, we could call it with times_x 3 [1;2;3;4;5] to get [3;6;9;12;15].

Beyond this I recommend looking into how map and reduce functions work in general.

I hope this answer was adequate at addressing your question.