{-# OPTIONS --cubical --safe #-}
module Lenses where
open import Prelude
record LensPart (A : Set a) (B : Set b) : Set (a ℓ⊔ b) where
field
get : B
set : B → A
open LensPart public
record Lens (A : Set a) (B : Set b) : Set (a ℓ⊔ b) where
field
into : A → LensPart A B
get-set : ∀ s v → into (into s .set v) .get ≡ v
set-get : ∀ s → into s .set (into s .get) ≡ s
set-set : ∀ s v₁ v₂ → into (into s .set v₁) .set v₂ ≡ into s .set v₂
open Lens public
infixl 4 _[_] _[_]≔_
_[_] : A → Lens A B → B
xs [ l ] = l .into xs .get
_[_]≔_ : A → Lens A B → B → A
xs [ l ]≔ x = l .into xs .set x
infixr 9 _⋯_
_⋯_ : Lens A B → Lens B C → Lens A C
(ab ⋯ bc) .into xs =
let ab-xs = ab .into xs
bc-ys = bc .into (ab-xs .get)
in λ where .get → bc-ys .get
.set → ab-xs .set ∘ bc-ys .set
(ab ⋯ bc) .get-set s v = cong _[ bc ] (ab .get-set s _) ; bc .get-set (ab .into s .get) v
(ab ⋯ bc) .set-get s = cong (s [ ab ]≔_) (bc .set-get (ab .into s .get)) ; ab .set-get s
(ab ⋯ bc) .set-set s v₁ v₂ = ab .set-set s _ _ ; cong (s [ ab ]≔_) (cong (_[ bc ]≔ v₂) (ab .get-set _ _) ; bc .set-set _ _ _)
⦅fst⦆ : Lens (A × B) A
⦅fst⦆ .into (x , y) .get = x
⦅fst⦆ .into (_ , y) .set x = x , y
⦅fst⦆ .get-set _ _ = refl
⦅fst⦆ .set-get _ = refl
⦅fst⦆ .set-set _ _ _ = refl
⦅snd⦆ : Lens (A × B) B
⦅snd⦆ .into (x , y) .get = y
⦅snd⦆ .into (x , _) .set y = x , y
⦅snd⦆ .get-set _ _ = refl
⦅snd⦆ .set-get _ = refl
⦅snd⦆ .set-set _ _ _ = refl
⦅pair⦆ : Bool → Lens (A × A) A
⦅pair⦆ = bool ⦅fst⦆ ⦅snd⦆