(* use a type definition as abbreviation *)
type ('a,'b) bagt = ('a * 'b) list;
type rb = (real,int)bagt ;

signature RBAG = sig

  val new: rb ; (* rb is imported... 
                   the value is bound into the structure *)
  val add: real * rb -> rb ;
  val del: real * rb -> rb ;
  val num: real * rb -> int ;
  val empty: rb -> bool ;

  (* hiding delall by leaving it out *)
  (* hiding ins by leaving it out *)

end;

structure bag = struct

  (* op new *)
  val new = nil ; (* why not this: fun new = nil ; *)

  (* op add *)
  fun add (elt,nil) = [(elt,1)]
    | add (elt,(e,c)::xs) =
        if e = elt 
          then [(e,c+1)] @ xs
          else [(e,c)] @ add(elt,xs) ;
    
  (* op del *)
  fun del (elt,nil) = nil
    | del (elt,(e,c)::xs) = 
        if e=elt andalso c=1 then 
          xs 
        else if e=elt then 
          [(e,c-1)] @ xs
        else
          [(e,c)] @ del(elt,xs) ;

  (* op delall *)
  fun delall (elt,nil) = nil
    | delall (elt,(e,c)::xs) =
        if e=elt then xs else [(e,c)] @ delall(elt,xs) ;

  (* op num *)
  fun num (elt,nil) = 0 
    | num (elt,(e,c)::xs) =
        if e=elt then c else num(elt,xs) ;

  (* op ins *)
  fun ins (elt,nil) = false
    | ins (elt,(e,c)::xs) = 
        if e=elt then true else ins(elt,xs) ;

  (* op empty *)
  fun empty M = null(M) ;
  
end;

structure rbag: RBAG = bag;

(* try these... explain
 val num: ''a * rilist -> int;
 val empty: 'a list -> bool;
*)

(* note... changing a value imported into signature *)
type ('a,'b,'c) bagt = ('a * 'b * 'c) list;
(* the sig RBAG will still require (real,int)bagt the old way *)
type rb = (real,int,bool)bagt;
type foob = (int,int,bool)bagt;


(*===========================================*)