packages feed

Agda-2.3.2.2: test/succeed/Copatterns.agda

{-# OPTIONS --copatterns #-}
module Copatterns where

open import Common.Equality

record _×_ (A B : Set) : Set where
  constructor _,_
  field
    fst : A
    snd : B
open _×_

pair : {A B : Set} → A → B → A × B
fst (pair a b) = a
snd (pair a b) = b

swap : {A B : Set} → A × B → B × A
fst (swap p) = snd p
snd (swap p) = fst p

swap3 : {A B C : Set} → A × (B × C) → C × (B × A)
fst (swap3 t)       = snd (snd t)
fst (snd (swap3 t)) = fst (snd t)
snd (snd (swap3 t)) = fst t

-- should also work if we shuffle the clauses
swap4 : {A B C D : Set} → A × (B × (C × D)) → D × (C × (B × A))
fst (snd (swap4 t))       = fst (snd (snd t))
snd (snd (snd (swap4 t))) = fst t
fst (swap4 t)             = snd (snd (snd t))
fst (snd (snd (swap4 t))) = fst (snd t)

-- State monad example

record State (S A : Set) : Set where
  constructor state
  field
    runState : S → A × S
open State

record Monad (M : Set → Set) : Set1 where
  constructor monad
  field
    return : {A : Set}   → A → M A
    _>>=_  : {A B : Set} → M A → (A → M B) → M B
open Monad {{...}}

stateMonad : {S : Set} → Monad (State S)
runState (return {{stateMonad}} a  ) s  = a , s
runState (_>>=_  {{stateMonad}} m k) s₀ =
  let a , s₁ = runState m s₀
  in  runState (k a) s₁

leftId : {A B S : Set}(a : A)(k : A → State S B) → (return a >>= k) ≡ k a
leftId a k = refl

rightId : {A B S : Set}(m : State S A) → (m >>= return) ≡ m
rightId m = refl

assoc : {A B C S : Set}(m : State S A)(k : A → State S B)(l : B → State S C) →
   ((m >>= k) >>= l) ≡ (m >>= λ a → k a >>= l)
assoc m k l = refl

-- multiple clauses with abstractions

fswap3 : {A B C X : Set} → (X → A) × ((X → B) × C) → (X → C) × (X → (B × A))
fst (fswap3 t) x       = snd (snd t)
fst (snd (fswap3 t) y) = fst (snd t) y
snd (snd (fswap3 t) z) = fst t z