I have these types :
type position = float * float
type node = position
I've written those modules to create my Map :
module MyMap =
struct
type t = node
let compare (a1,b1) (a2,b2) =
if a1 > a2 then 1
else if a1 < a2 then -1
else if b1 > b2 then 1
else if b1 < b2 then -1
else 0
end
module DistMap = Map.Make(MyMap)
I've tried to write functions that used iter
but my attempts to formulate my ideas in a correct syntax were unsuccessful.
My goal would be able to have a function that takes a Map as argument and return a tuple of the minimum element and its key.
Thanks.
If you're asking for the minimum key and its corresponding element, that's easy: use DistMap.min_binding_opt
, or DistMap.min_binding
if you're fine with raising an exception on an empty map.
If you're asking for the minimum element and its corresponding key, you will want to use a fold. Luckily, the DistMap
module returned by Map.Make
exposes a fold
function, so you don't have to do extra allocation by, say, calling to_seq
and doing a fold on the result. In addition, because the type of elements in a map is not constrained by the functor application (i.e., you can create a map with any element type), you will need the client to supply a comparison function for the element type.
DistMap.fold
has type (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b
, so we'll have to instantiate 'b
in such a way as to keep track of both the key and the min element; in other words, we'll instantiate 'a
as the element type of the map (let’s call it t
), and 'b
as (key * t) option
(where key = position = float * float
).
Here's what the code might look like:
let min_element_and_its_key map ~compare_element =
let take_min key element key_and_min_element =
match key_and_min_element with
| None -> Some (key, element)
| Some (key_for_min_element, min_element) ->
if compare_element element min_element < 0
then Some (key, element)
else Some (key_for_min_element, min_element)
in
DistMap.fold take_min map None
min_element_and_its_key
will return None
on an empty map.
Example client code (which you can run in an ocaml repl) might look like:
let map = DistMap.(empty |> add (3., 3.) "a" |> add (4., 4.) "b") in
min_element_and_its_key map ~compare_element:String.compare;;
(* Output: *)
- : (node * string) option = Some ((3., 3.), "a")
In general, anytime that you want to traverse all keys/elements in a data structure and accumulate a value, a fold
is the way to go. iter
will sort of work, but you'll have to accumulate the value in mutable state instead of accumulating it directly as the return value of the function you're folding with.