List and Bag

spec
     GenerateList [Elem with sort Elem] =
     free
          types
           List[Elem]         ::=  nil | sort NonEmptyList[Elem];
           NonEmptyList[Elem] ::=  __ :: __ (first : Elem; rest :
                                   List[Elem])
     op
          __ :: __: Elem × List[Elem] -> List[Elem] %%right assoc
end

spec
     List[Elem with sort Elem] =
     GenerateList[Elem] with
      sort List[Elem], NonEmptyList[Elem],
      ops nil, __ :: __, first, rest
     and Nat with
      sorts Nat, Pos,
      preds __ <= __,__ >= __,__<__,__>__,
      ops  0, suc, pre,
           +__, abs, __ + __, __ - __, __ * __,
           __ div __, __ mod __, min, max, __ ^ __,
           1,2,3,4,5,6,7,8,9, __ :: __
then
     pred
          isEmpty: List[Elem]
     ops
           last:      List[Elem] ->? Elem;
           length:    List[Elem] -> Nat;
           __ ++ __ : List[Elem] × List[Elem] -> List[Elem];
           reverse:   List[Elem] -> List[Elem];
           take,drop: Nat × List[Elem] ->? List[Elem]
     vars
          x: Elem; n: Nat; L,K: List[Elem]
     %%          isEmpty:
     .          isEmpty(L) <=> L=nil
     %%          last:
     .          def last(L) <=> not isEmpty(L)
     .          last (x :: nil) = x
     .          last (x :: L) = last(L) if not L=nil
     %%          length:
     .          length (nil) = 0
     .          length (x :: L) = suc(length(L))
     %%          concatenating lists:
     .          nil ++ L = L
     .          x::L ++ K = x :: (L ++ K)
     %%          reverse:
     .          reverse(nil)=nil
     .          reverse(x::L)= reverse(L) ++ (x::nil)
     %%          take(n,L) - construct a list of the first n items of a list L:
     .          def take(n,L) <=> length(L) >= n
     .          take ( 0, L) = nil
     .          take ( suc(n), x :: L)  = x :: take(n,L) if def take( n, L)
     %%          drop(n,L) - remove the first n items of a list L:
     .          def drop(n,L) <=> length(L) >= n
     .          drop ( 0, L) = L
     .          drop ( suc(n), x :: L ) = drop(n,L) if def drop(n, L)
end

view
     Monoid_in_List [Elem]: Monoid to List [Elem] =
     sort
          Elem |-> List[Elem],
     ops
           0 |-> Nil,
           __+__ |-> __ ++ __
end

spec
     GenerateBag [Elem with sort Elem] =
     Nat with
      sorts Nat, Pos,
      preds __ <= __,__ >= __,__<__,__>__,
      ops  0, suc, pre,
           +__, abs, __ + __, __ - __, __ * __,
           __ div __, __ mod __, min, max, __ ^ __,
           1,2,3,4,5,6,7,8,9, __ :: __
     and List[Elem] with
      sorts List[Elem], NonEmptyList[Elem],
      pred  empty,
      ops   nil, __ :: __, first, rest,
            last, length, __ ++ __, reverse, take, drop
then
     op
          numberOf: Elem × List[Elem] -> Nat
     vars
          x,y:Elem; L: List
     .          numberOf (x,nil) = 0
     .          numberOf (x, y::L) = numberOf (x, L) if not x=y
     .          numberOf (x, y::L) = suc(numberOf (x, L)) if x=y
then
     free
     {
          type
               Bag[Elem] ::= quotient(List[Elem])
          vars
               x:Elem; K,L: List[Elem]
          .                quotient(K)=quotient(L) <=>
                numberOf(x,K) = numberOf(x,L)
     }
     %%          intended system of representatives:
     %%          functions B: Elem -> Nat,
     %%          where B(x)>0 for finitely many x. Any such function B
     %%          represents a set of lists L
     %%          with numberOf(x,L)=B(x) for all x in Elem.end

spec
     Bag[Elem with sort Elem] =
     GenerateBag[Elem] with
      sorts Nat, Pos, List[Elem], NonEmptyList[Elem], Bag[Elem],
      preds __ <= __,__ >= __,__<__,__>__, empty,
      ops  0, suc, pre,
           +__, abs, __ + __, __ - __, __ * __,
           __ div __, __ mod __, min, max, __ ^ __,
           1,2,3,4,5,6,7,8,9, __ :: __,
           nil, __ :: __, first, rest,
           last, length, __ ++ __, reverse, take, drop,
           numberOf, quotient
then
     preds
           __ elemOf __:     Elem * Bag[Elem];
           __ isSubsetOf __: Bag[Elem] * Bag[Elem]
     ops
           empty:                           Bag[Elem];
           numberOf:                         Bag[Elem] -> Nat;
           put, remove:                     Elem × Bag[Elem] -> Bag[Elem];
           __ union __, __ intersection __: Bag[Elem] * Bag[Elem] ->
                                            Bag[Elem]
     axiom
          empty = quotient(nil)
     vars
          x: Elem; B,C,D: Bag[Elem]; L: List[Elem]
     %%          numberOf - cast for the operation on List:
     .          numberOf(x,quotient(L)) = numberOf(x,L)
     %%          x  elemOf B:
     .          x elemOf B <=> numberOf(x,B) > 0
     %%          put(x,B) - add an element x to a bag B:
     .           put(x,B) = C <=>

           (forall y: Elem .  ( not y = x => numberOf (y,B) =
                              numberOf(y,C)) /\
                              ( y = x => numberOf (y,B)+1 = numberOf(y,C))
                              )

     %%          remove(x,B) - remove an element x from a bag B:
     .          remove(x,B) = B if numberOf(x,B)=0
     .          remove(x,B) = C /\
           (forall y: Elem . ( not y = x => numberOf (y,B) = numberOf(y,C))
                             /\
                             ( y = x => numberOf (y,B)-1 = numberOf (y,C)))

          if numberOf(x,B)>0
     %%          B isSubsetOf C:
     .          B isSubsetOf C <=> ( forall x: Elem . numberOf(x,B) <=
          numberOf(x,C) )
     %%          B union C:
     .           B union C = D <=> ( forall x: Elem .           numberOf(x,D) = numberOf(x,B) + numberOf(x,C) )
     %%          S intersection T:
     .           B intersection C = D <=> ( forall x: Elem . numberOf(x,D) = min ( numberOf(x,B), numberOf(x,C) ) )

end

view
     PartialOrder_in_Bag [Elem]: PartialOrder to Bag[Elem] =
     sort
          Elem |-> Bag[Elem],
     pred
          __ <= __ |-> __ isSubsetOf __
end



Back to the Basic Datatypes in CASL
Markus Roggenbach last update March 5, 1999.