2014-11-23 4 views
1

У меня есть библиотека, которая реализует набор (интерфейс с документацией, доступной здесь: http://pastebin.com/j9QUyN1G). Я понимаю, все, кроме от этого фрагмента:Использовать Set.Make.iter для преобразования элементов набора?

val iter : ('a -> unit) -> 'a t -> unit 
(** [iter f s] applies [f] to all elements in set [s]. The elements 
    are passed to [f] in increasing order with respect to the ordering 
    used to create the set. *) 

Так iter принимает функцию в качестве одного из заданы параметры и применяет его ко всем элементам набора. Поэтому я ожидал бы что-то вроде ('a -> 'a), которое берет элемент набора и изменяет его на элемент того же типа с другим значением или ('a -> 'b), который принимает 'a t и преобразует его в 'b t. А вместо этого iter выполняет функцию типа ('a -> unit), а также возвращает unit, а не 'a t, а не 'b t.

Итак, как должна выглядеть функция примера, обращенная к iter?

ответ

3

iter не меняет элементы набора. Он выполняется исключительно для его побочных эффектов. Вы можете использовать его для печати элементов, например: структура данных

module StringSet = Set.Make(String) 
… 
StringSet.iter print_endline ss 

Множества неизменна, так что вы не можете изменить элементы набора. Вы можете построить новый набор, элементы которого получены из существующего набора. Для списка есть функция map, которая принимает список [x1; …; xn] и возвращает новый список [f x1; …; f xn]. Подобной функции нет в модуле Set, потому что элементы в наборе не сохраняются в порядке, выбранном вызывающим: нет такой вещи, как набор со своими элементами в порядке, полученном из другого набора. Если вы хотите построить набор из образов элементов набора, вставьте новые элементы по одному.

module Int = struct 
    type t = int 
    let compare = Pervasives.compare 
end 
module IntSet = Set.Make(Int) 
module StringSet = Set.Make(String) 
let int_to_string_set is = 
    IntSet.fold (fun i ss -> StringSet.add (string_of_int i) ss) is StringSet.empty 
0

Было бы функции с побочными эффектами, например:

Let p x = Printf.printf "%d\n" x 
1

iter принимает такую ​​функцию, которая принимает аргумент типа 'a делать с ней все, что он, Что и возвращает значение типа unit. Другими словами, он оценивается по побочным эффектам, поскольку он не может вернуть ничего полезного.

Что вы ищете является map функцией, которая обычно принимает функцию типа 'a -> 'b контейнера с элементами типа 'a и возвращает контейнер с элементами типа 'b. К сожалению, интерфейс, который вы показали, не обеспечивает такую ​​функцию. Но это не проблема, поскольку она обеспечивает функцию fold, то есть самый общий итератор. Имея только fold вы можете реализовать любые другие iteratos, как map, iter, exists и т.д ... На самом деле в Core библиотеки вы можете найти Container.Make функтор, который будет автоматически выводит общий интерфейс контейнера только из одной функции - fold. Кроме того, вы можете определить карту самостоятельно:

let map f xs = 
    fold (fun x ys -> add (f x) ys) xs empty 
Смежные вопросы