Source code on Github
{-# OPTIONS --allow-unsolved-metas #-}
module Common.Data where

open import Prelude.Init; open SetAsType
open import Prelude.DecEq
open import Prelude.Decidable
open import Prelude.Semigroup
open import Prelude.Bifunctor

DATA = String

record ToData (A : Type) : Type where
  field
    serialise     : A  DATA
    serialise-inj : Injective≡ serialise
    deserialise   : (d : DATA)  Dec ( λ a  d  serialise a)

  deserialise∘serialise :  a  deserialise (serialise a)  yes (a , refl)
  deserialise∘serialise a
    with deserialise (serialise a)
  ... | no ¬p = ⊥-elim (¬p (a , refl))
  ... | yes (_ , ser≡)
    with reflserialise-inj ser≡
    rewrite ser≡
    = refl
open ToData ⦃...⦄ public

private variable A B C : Type 

dec-elim : (A  C)  (¬ A  C)  Dec A  C
dec-elim f g = λ where
  (yes a)  f a
  (no ¬a)  g ¬a

open Fun
ToData↔ :  ToData A   (eq : A  B)  Injective≡ (eq .Inverse.f⁻¹)  ToData B
ToData↔ record { f = A→B ; f⁻¹ = B→A; inverse = _ , B→A→B } B→A-inj = λ where
  .serialise  serialise  B→A
  .serialise-inj  B→A-inj  serialise-inj
  .deserialise 
    Nullary.map′  (a , d≡)  A→B a , trans d≡ (cong serialise $ sym $ B→A→B _))
                  (b , d≡)  B→A b , d≡)
     deserialise

instance
  ToData-DATA : ToData DATA
  ToData-DATA = λ where
    .serialise  id
    .serialise-inj  id
    .deserialise _  yes (-, refl)

  ToData-Unit : ToData 
  ToData-Unit .serialise tt = "tt"
  ToData-Unit .serialise-inj refl = refl
  ToData-Unit .deserialise d = Nullary.map′ -,_ proj₂ (d  "tt")

  ToData-Bool : ToData Bool
  ToData-Bool .serialise = λ where true   "true"; false  "false"
  ToData-Bool .serialise-inj {false}{false} refl = refl
  ToData-Bool .serialise-inj {true}{true}   refl = refl
  ToData-Bool .deserialise d
    = Nullary.map′
      Sum.[ true ,_ , false ,_ ]
       where (true , d≡)  inj₁ d≡; (false , d≡)  inj₂ d≡)
      ¿ (d  "true")  (d  "false") ¿

  ToData-⊎ :  ToData A    ToData B   ToData (A  B)
  ToData-⊎ .serialise = λ where
    (inj₁ a)  "0"  serialise a
    (inj₂ b)  "1"  serialise b
  ToData-⊎ .serialise-inj = {!!}
  ToData-⊎ .deserialise d = {!!}

  ToData-× :  ToData A    ToData B   ToData (A × B)
  ToData-× .serialise (a , b) = serialise a  "⨾"  serialise b
  ToData-× .serialise-inj = {!!}
  ToData-× .deserialise d = {!!}