|
| 1 | +{-# OPTIONS --erasure #-} |
| 2 | + |
| 3 | +module Data.Map.Maybe |
| 4 | + {- |
| 5 | + This module adds functions for the 'Maybe' type |
| 6 | + that are analogous to the functions in 'Data.Map'. |
| 7 | + This is used to make proofs for 'Data.Map' more transparent. |
| 8 | + -} where |
| 9 | + |
| 10 | +open import Haskell.Law.Equality |
| 11 | +open import Haskell.Prelude hiding (null; map; filter) |
| 12 | + |
| 13 | +open import Haskell.Data.Maybe using |
| 14 | + ( isJust |
| 15 | + ) |
| 16 | + |
| 17 | +{----------------------------------------------------------------------------- |
| 18 | + Data.Maybe |
| 19 | + Functions |
| 20 | +------------------------------------------------------------------------------} |
| 21 | + |
| 22 | +null : Maybe a → Bool |
| 23 | +null Nothing = True |
| 24 | +null (Just x) = False |
| 25 | + |
| 26 | +update : (a → Maybe a) → Maybe a → Maybe a |
| 27 | +update f Nothing = Nothing |
| 28 | +update f (Just x) = f x |
| 29 | + |
| 30 | +filter : (a → Bool) → Maybe a → Maybe a |
| 31 | +filter p Nothing = Nothing |
| 32 | +filter p (Just x) = if p x then Just x else Nothing |
| 33 | + |
| 34 | +-- | Degenerate 'filter', does not look at the contents. |
| 35 | +-- Similar to 'guard'. |
| 36 | +filt : Bool → Maybe a → Maybe a |
| 37 | +filt True m = m |
| 38 | +filt False m = Nothing |
| 39 | + |
| 40 | +mapMaybe : (a → Maybe b) → Maybe a → Maybe b |
| 41 | +mapMaybe f Nothing = Nothing |
| 42 | +mapMaybe f (Just x) = f x |
| 43 | + |
| 44 | +unionWith : (a → a → a) → Maybe a → Maybe a → Maybe a |
| 45 | +unionWith f Nothing my = my |
| 46 | +unionWith f (Just x) Nothing = Just x |
| 47 | +unionWith f (Just x) (Just y) = Just (f x y) |
| 48 | + |
| 49 | +-- | Left-biased union. |
| 50 | +union : Maybe a → Maybe a → Maybe a |
| 51 | +union = unionWith (λ x y → x) |
| 52 | + |
| 53 | +intersectionWith : (a → b → c) → Maybe a → Maybe b → Maybe c |
| 54 | +intersectionWith f (Just x) (Just y) = Just (f x y) |
| 55 | +intersectionWith _ _ _ = Nothing |
| 56 | + |
| 57 | +disjoint : Maybe a → Maybe b → Bool |
| 58 | +disjoint m = null ∘ intersectionWith const m |
| 59 | + |
| 60 | +{----------------------------------------------------------------------------- |
| 61 | + Properties |
| 62 | + union |
| 63 | +------------------------------------------------------------------------------} |
| 64 | + |
| 65 | +-- |
| 66 | +prop-union-empty-right |
| 67 | + : ∀ {ma : Maybe a} |
| 68 | + → union ma Nothing ≡ ma |
| 69 | +-- |
| 70 | +prop-union-empty-right {_} {Nothing} = refl |
| 71 | +prop-union-empty-right {_} {Just x} = refl |
| 72 | + |
| 73 | +-- | 'unionWith' is symmetric if we 'flip' the function. |
| 74 | +-- Note that 'union' is left-biased, not symmetric. |
| 75 | +-- |
| 76 | +prop-unionWith-sym |
| 77 | + : ∀ {f : a → a → a} {ma mb : Maybe a} |
| 78 | + → unionWith f ma mb ≡ unionWith (flip f) mb ma |
| 79 | +-- |
| 80 | +prop-unionWith-sym {_} {f} {Nothing} {Nothing} = refl |
| 81 | +prop-unionWith-sym {_} {f} {Just x} {Nothing} = refl |
| 82 | +prop-unionWith-sym {_} {f} {Nothing} {Just y} = refl |
| 83 | +prop-unionWith-sym {_} {f} {Just x} {Just y} = refl |
| 84 | + |
| 85 | +-- |
| 86 | +prop-union-assoc |
| 87 | + : ∀ {ma mb mc : Maybe a} |
| 88 | + → union (union ma mb) mc ≡ union ma (union mb mc) |
| 89 | +-- |
| 90 | +prop-union-assoc {_} {Nothing} {mb} {mc} = refl |
| 91 | +prop-union-assoc {_} {Just x} {Nothing} {mc} = refl |
| 92 | +prop-union-assoc {_} {Just x} {Just y} {Nothing} = refl |
| 93 | +prop-union-assoc {_} {Just x} {Just y} {Just z} = refl |
| 94 | + |
| 95 | +-- | 'union' is symmetric if at most one argument is 'Just'. |
| 96 | +-- |
| 97 | +prop-union-sym |
| 98 | + : ∀ {ma mb : Maybe a} |
| 99 | + → disjoint ma mb ≡ True |
| 100 | + → union ma mb ≡ union mb ma |
| 101 | +-- |
| 102 | +prop-union-sym {_} {Nothing} {Nothing} eq = refl |
| 103 | +prop-union-sym {_} {Nothing} {Just x} eq = refl |
| 104 | +prop-union-sym {_} {Just x} {Nothing} eq = refl |
| 105 | + |
| 106 | +-- |
| 107 | +prop-union-left |
| 108 | + : ∀ (x : a) (mb : Maybe a) |
| 109 | + → union (Just x) mb ≡ Just x |
| 110 | +-- |
| 111 | +prop-union-left x Nothing = refl |
| 112 | +prop-union-left x (Just y) = refl |
| 113 | + |
| 114 | +{----------------------------------------------------------------------------- |
| 115 | + Properties |
| 116 | + intersection |
| 117 | +------------------------------------------------------------------------------} |
| 118 | +-- |
| 119 | +prop-isJust-intersectionWith |
| 120 | + : ∀ {ma : Maybe a} {mb : Maybe b} {f : a → b → c} |
| 121 | + → isJust (intersectionWith f ma mb) |
| 122 | + ≡ (isJust ma && isJust mb) |
| 123 | +-- |
| 124 | +prop-isJust-intersectionWith {_} {_} {_} {Nothing} = refl |
| 125 | +prop-isJust-intersectionWith {_} {_} {_} {Just x} {Nothing} = refl |
| 126 | +prop-isJust-intersectionWith {_} {_} {_} {Just x} {Just y} = refl |
| 127 | + |
| 128 | +{----------------------------------------------------------------------------- |
| 129 | + Properties |
| 130 | + filter |
| 131 | +------------------------------------------------------------------------------} |
| 132 | +-- | |
| 133 | +-- Since 'union' is left-biased, |
| 134 | +-- filtering commutes with union if the predicate is constant. |
| 135 | +-- |
| 136 | +-- If the predicate is not constant, there are counterexamples. |
| 137 | +prop-filter-union |
| 138 | + : ∀ (p : a → Bool) {m1 m2 : Maybe a} |
| 139 | + → (∀ (x y : a) → p x ≡ p y) |
| 140 | + → filter p (union m1 m2) |
| 141 | + ≡ union (filter p m1) (filter p m2) |
| 142 | +-- |
| 143 | +prop-filter-union p {Nothing} {m2} flat = refl |
| 144 | +prop-filter-union p {Just x} {Nothing} flat |
| 145 | + with p x |
| 146 | +... | True = refl |
| 147 | +... | False = refl |
| 148 | +prop-filter-union p {Just x} {Just y} flat |
| 149 | + rewrite flat x y |
| 150 | + with p y |
| 151 | +... | True = refl |
| 152 | +... | False = refl |
| 153 | + |
| 154 | +-- |
| 155 | +@0 prop-filter-|| |
| 156 | + : ∀ {ma : Maybe a} {p q : a → Bool} |
| 157 | + → filter (λ x → p x || q x) ma |
| 158 | + ≡ union (filter p ma) (filter q ma) |
| 159 | +-- |
| 160 | +prop-filter-|| {_} {Nothing} {p} {q} = refl |
| 161 | +prop-filter-|| {_} {Just x} {p} {q} |
| 162 | + with p x | q x |
| 163 | +... | True | True = refl |
| 164 | +... | True | False = refl |
| 165 | +... | False | True = refl |
| 166 | +... | False | False = refl |
| 167 | + |
| 168 | +-- | |
| 169 | +-- 'filt' is a special case of 'filter'. |
| 170 | +prop-filter-filt |
| 171 | + : ∀ (b : Bool) (m : Maybe a) |
| 172 | + → filter (λ x → b) m |
| 173 | + ≡ filt b m |
| 174 | +-- |
| 175 | +prop-filter-filt False Nothing = refl |
| 176 | +prop-filter-filt True Nothing = refl |
| 177 | +prop-filter-filt False (Just x) = refl |
| 178 | +prop-filter-filt True (Just x) = refl |
| 179 | + |
| 180 | +{----------------------------------------------------------------------------- |
| 181 | + Properties |
| 182 | + filt |
| 183 | +------------------------------------------------------------------------------} |
| 184 | +-- | |
| 185 | +-- Since 'union' is left-biased, |
| 186 | +-- filtering commutes with union if the predicate is constant. |
| 187 | +-- |
| 188 | +-- If the predicate is not constant, there are counterexamples. |
| 189 | +prop-filt-|| |
| 190 | + : ∀ (x y : Bool) {m : Maybe a} |
| 191 | + → filt (x || y) m |
| 192 | + ≡ union (filt x m) (filt y m) |
| 193 | +-- |
| 194 | +prop-filt-|| False y {Nothing} = refl |
| 195 | +prop-filt-|| False y {Just x} = refl |
| 196 | +prop-filt-|| True False {Nothing} = refl |
| 197 | +prop-filt-|| True False {Just x} = refl |
| 198 | +prop-filt-|| True True {Nothing} = refl |
| 199 | +prop-filt-|| True True {Just x} = refl |
| 200 | + |
| 201 | +-- |
| 202 | +prop-filt-union |
| 203 | + : ∀ (x : Bool) {m1 m2 : Maybe a} |
| 204 | + → filt x (union m1 m2) |
| 205 | + ≡ union (filt x m1) (filt x m2) |
| 206 | +-- |
| 207 | +prop-filt-union False {Nothing} {m2} = refl |
| 208 | +prop-filt-union True {Nothing} {m2} = refl |
| 209 | +prop-filt-union False {Just y} {Nothing} = refl |
| 210 | +prop-filt-union True {Just y} {Nothing} = refl |
| 211 | +prop-filt-union False {Just y} {Just z} = refl |
| 212 | +prop-filt-union True {Just y} {Just z} = refl |
| 213 | + |
| 214 | +-- |
| 215 | +prop-filt-filt |
| 216 | + : ∀ (x y : Bool) (m : Maybe a) |
| 217 | + → filt x (filt y m) ≡ filt (x && y) m |
| 218 | +-- |
| 219 | +prop-filt-filt False False m = refl |
| 220 | +prop-filt-filt False True m = refl |
| 221 | +prop-filt-filt True False m = refl |
| 222 | +prop-filt-filt True True m = refl |
0 commit comments