Bag

A bag is also known as a multiset. It is a modificaiton of the concept of a set which allows for multiple instances of each element. Each item then also has a multiplicity, defined by the number of instances of that item in the multiset.

Bag a

empty : {} -> Bag *

Create an empty bag

single : a -> Bag a

Create a bag with a single instance of an item in it

repeat : a, Nat -> Bag a

Create a bag with multiple instances of an item in it

fromList : List k -> Bag k

Create a bag from a list.

expect
    bag = ["a", "a", "b"] |> Bag.fromList
    (bag |> Bag.count "a" == 2) && (bag |> Bag.count "b" == 1)

fromSet : Set k -> Bag k

Construct a bag from a set.

expect
    bag = Set.empty {} |> Set.insert "a" |> Set.insert "a" |> Set.insert "b" |> Bag.fromSet
    (bag |> Bag.count "a" == 1) && (bag |> Bag.count "b" == 1)

join : Bag k, Bag k -> Bag k

Join two bags together, adding the number of items in each bag.

union : Bag k, Bag k -> Bag k

Take the union of the two bags, defined by the biggest number of instances per item in both bags.

intersection : Bag k, Bag k -> Bag k

Take the intersection of the two bags, defined by the smallest number of instances per item in both bags. If an item is only present in one of the bags, the smallest number is zero and then it is not included in the resulting bag.

difference : Bag k, Bag k -> Bag k

Take the difference of the two bags, defined by removing the number of instances of the items in the second bag from the first bag.

size : Bag * -> Nat

Get the total number of items in the bag

isEmpty : Bag * -> Bool

Is the bag empty?

containsAny : Bag k, k -> Bool

Does the bag contain any of the item?

contains : Bag k, Nat, k -> Bool

Does the bag contain the given number, or more, of the item?

count : Bag k, k -> Nat

Get the number of instances (multiplicity) of the given item

includedIn : Bag k, Bag k -> Bool

Is the first bag included in the second bag? This is a modification of the concept of subset. Bag A is included in bag B if all the items in bag A have lower or equal multiplicity compared with the items in bag B.

insert : Bag a, Nat, a -> Bag a

Insert a number of instances of an item into a bag

remove : Bag k, Nat, k -> Bag k

Remove a number of instances of an item in the bag. If the same number or more of instances are removed than there are in the bag, remove all the items from the bag.

removeAll : Bag k, k -> Bag k

Remove all instances of an item from the bag.

toList : Bag k -> List k

Convert the bag to a list

expect empty {} |> insert 2 "a" |> insert 3 "b" |> toList == ["a", "a", "b", "b", "b"]

walk : Bag k, state, (state, k, Nat -> state) -> state

Walk the items of the bag and their multiplicities, threading state along the way.

scaleWith : Bag k, Nat -> Bag k

Rescale the multiplicities of the items with the given integer.

map : Bag a, (a -> b) -> Bag b

Map a function over the elements of the bag, combining the multiplicities of the new items appropriately.

joinMap : Bag a, (a -> Bag b) -> Bag b

Map a bag-creating function over the elements of the bag, joining all the resulting bags together. The resulting multiplicities in each bag are scaled with the original multiplicity of the item the bag is created from.

expect
    Bag.empty {} |> Bag.insert 2 "a" |> Bag.insert 3 "b" |> Bag.joinMap \s ->
        s |> Bag.repeat 3
    == Bag.empty {} |> Bag.insert 6 "a" |> Bag.insert 9 "b"

keepIf : Bag a, ( ( a, Nat ) -> Bool) -> Bag a

Keep only items that fulfill the given predicative, which refers to both the item and its multiplicity.

dropIf : Bag a, ( ( a, Nat ) -> Bool) -> Bag a

Drop all items that fulfill the given predicative, which refers to both the item and its multiplicity.