2014-11-02 40 views
3

我正在試驗Core的List.fold_left使用無標籤的Core.Std.List.fold_left

# List.fold_left;; 
- : 'a Core.Std.List.t -> init:'b -> f:('b -> 'a -> 'b) -> 'b = <fun> 

當我指定的標籤,它工作正常:

# List.fold_left [1;2;3] ~init:0 ~f:(+);; 
- : int = 6     

,但我得到了不同的結果,當我不指定標籤:

# List.fold_left [1;2;3] 0 (+);; 
- : init:(int -> (int -> int -> int) -> '_a) -> 
    f:((int -> (int -> int -> int) -> '_a) -> 
     int -> int -> (int -> int -> int) -> '_a) -> 
    '_a 
= <fun> 

與其他部分應用程序也屈服非直覺類型。爲什麼我可以在列表參數後添加任意數量的0?

# List.fold_left [1;2;3] 0;; 
- : init:(int -> '_a) -> f:((int -> '_a) -> int -> int -> '_a) -> '_a = <fun> 

# List.fold_left [1;2;3] 0 0;; 
- : init:(int -> int -> '_a) -> 
    f:((int -> int -> '_a) -> int -> int -> int -> '_a) -> '_a 
= <fun> 

一些其他功能表現出相同的行爲:

# let app ~f ~x = f x;; 
val app : f:('a -> 'b) -> x:'a -> 'b = <fun> 

# app (fun x -> x + 1) 1;; 
- : f:('a -> (int -> int) -> int -> 'b) -> x:'a -> 'b = <fun> 

但是,當沒有給出標籤應用了一些標記功能能夠返回預期的結果。例如:

# List.map;; 
- : 'a Core.Std.List.t -> f:('a -> 'b) -> 'b Core.Std.List.t = <fun> 

# List.map [1;2;3] (fun x -> x + 1);; 
- : int Core.Std.List.t = [2; 3; 4] 

爲什麼當沒有給出標籤應用了一些函數返回值是非直觀的,而其他工作如預期?

回答

4

根據the manual你只能忽略標籤「如果一個應用程序是總(省略所有可選參數)」與重要的告誡「其功能就像ListLabels.fold_left,其結果類型是類型變量將永遠不會被視爲完全適用。」

因此,由於核心的fold_left的結果類型當然也是一個類型變量,所以不能在沒有標籤的情況下調用它。當你這樣做時會發生什麼情況是位置參數被解釋爲由fold_left產生的函數的參數,它仍然等待你提供帶標籤的參數。

1

@ sepp2k的回答清楚地解釋了這裏發生的事情。讓我再補充一點。

簡而言之,不要忽略標籤功能的標籤。他們在那裏是爲了目的。我相信沒有人可以正確處理標籤忽略。您應該始終打開警告6並使其成爲錯誤:

$ ocamlc -w +6 -warn-error +6 file.ml 
File "file.ml", line 2, characters 17-18: 
Warning 6: labels were omitted in the application of this function. 
File "file.ml", line 1: 
Error: Some fatal warnings were triggered (1 occurrences)