2020-05-18 15:59:07 +03:00
|
|
|
module Data.So
|
|
|
|
|
2020-06-12 00:14:11 +03:00
|
|
|
import Data.Bool
|
|
|
|
|
|
|
|
%default total
|
|
|
|
|
2020-05-18 15:59:07 +03:00
|
|
|
||| Ensure that some run-time Boolean test has been performed.
|
|
|
|
|||
|
|
|
|
||| This lifts a Boolean predicate to the type level. See the function `choose`
|
|
|
|
||| if you need to perform a Boolean test and convince the type checker of this
|
|
|
|
||| fact.
|
|
|
|
|||
|
|
|
|
||| If you find yourself using `So` for something other than primitive types,
|
|
|
|
||| it may be appropriate to define a type of evidence for the property that you
|
|
|
|
||| care about instead.
|
|
|
|
public export
|
|
|
|
data So : Bool -> Type where
|
|
|
|
Oh : So True
|
|
|
|
|
|
|
|
export
|
2020-06-12 00:14:11 +03:00
|
|
|
Uninhabited (So False) where
|
2020-05-18 15:59:07 +03:00
|
|
|
uninhabited Oh impossible
|
|
|
|
|
|
|
|
||| Perform a case analysis on a Boolean, providing clients with a `So` proof
|
|
|
|
export
|
|
|
|
choose : (b : Bool) -> Either (So b) (So (not b))
|
|
|
|
choose True = Left Oh
|
|
|
|
choose False = Right Oh
|
|
|
|
|
2020-06-12 00:14:11 +03:00
|
|
|
export
|
|
|
|
eqToSo : b = True -> So b
|
|
|
|
eqToSo Refl = Oh
|
|
|
|
|
|
|
|
export
|
|
|
|
soToEq : So b -> b = True
|
|
|
|
soToEq Oh = Refl
|
|
|
|
|
|
|
|
||| If `b` is True, `not b` can't be True
|
|
|
|
export
|
|
|
|
soToNotSoNot : So b -> Not (So (not b))
|
|
|
|
soToNotSoNot Oh = uninhabited
|
|
|
|
|
|
|
|
||| If `not b` is True, `b` can't be True
|
|
|
|
export
|
|
|
|
soNotToNotSo : So (not b) -> Not (So b)
|
|
|
|
soNotToNotSo = flip soToNotSoNot
|
|
|
|
|
|
|
|
export
|
|
|
|
soAnd : {a : Bool} -> So (a && b) -> (So a, So b)
|
|
|
|
soAnd soab with (choose a)
|
|
|
|
soAnd {a=True} soab | Left Oh = (Oh, soab)
|
|
|
|
soAnd {a=True} soab | Right prf = absurd prf
|
|
|
|
soAnd {a=False} soab | Right prf = absurd soab
|
|
|
|
|
|
|
|
export
|
|
|
|
andSo : (So a, So b) -> So (a && b)
|
|
|
|
andSo (Oh, Oh) = Oh
|
|
|
|
|
|
|
|
export
|
|
|
|
soOr : {a : Bool} -> So (a || b) -> Either (So a) (So b)
|
|
|
|
soOr soab with (choose a)
|
|
|
|
soOr {a=True} _ | Left Oh = Left Oh
|
|
|
|
soOr {a=False} _ | Left Oh impossible
|
|
|
|
soOr {a=False} soab | Right Oh = Right soab
|
|
|
|
soOr {a=True} _ | Right Oh impossible
|
|
|
|
|
|
|
|
export
|
|
|
|
orSo : Either (So a) (So b) -> So (a || b)
|
|
|
|
orSo (Left Oh) = Oh
|
|
|
|
orSo (Right Oh) = rewrite orTrueTrue a in
|
|
|
|
Oh
|