------------------------------------------------------------------------
-- The Agda standard library
--
-- Documentation for permutation over `List`s
------------------------------------------------------------------------

module README.Data.List.Relation.Binary.Permutation where

open import Algebra.Structures using (IsCommutativeMonoid)
open import Data.List.Base
open import Data.Nat using (; _+_)
open import Relation.Binary.PropositionalEquality
  using (_≡_; refl; sym; cong; setoid)

------------------------------------------------------------------------
-- Permutations

-- As an alternative to pointwise equality you might consider two lists
-- to be equal if they contain the same elements regardless of the order
-- of the elements. This is known as either "set equality" or a
-- "permutation".

-- The easiest-to-use formalisation of this relation is found in the
-- module:

open import Data.List.Relation.Binary.Permutation.Propositional

-- The permutation relation is written as `_↭_` and has four
-- constructors. The first `refl` says that a list is always
-- a permutation of itself, the second `prep` says that if the
-- heads of the lists are the same they can be skipped, the third
-- `swap` says that the first two elements of the lists can be
-- swapped and the fourth `trans` says that permutation proofs
-- can be chained transitively.

-- For example a proof that two lists are a permutation of one
-- another can be written as follows:

lem₁ : 1  2  3  []  3  1  2  []
lem₁ = trans (prep 1 (swap 2 3 refl)) (swap 1 3 refl)

-- In practice it is difficult to parse the constructors in the
-- proof above and hence understand why it holds. The
-- `PermutationReasoning` module can be used to write this proof
-- in a much more readable form:

open PermutationReasoning

lem₂ : 1  2  3  []  3  1  2  []
lem₂ = begin
  1  2  3  []  ↭⟨ prep 1 (swap 2 3 refl) 
  1  3  2  []  ↭⟨ swap 1 3 refl 
  3  1  2  []  

-- As might be expected, properties of the permutation relation may be
-- found in:

open import Data.List.Relation.Binary.Permutation.Propositional.Properties
  using (map⁺; ++-isCommutativeMonoid)

lem₃ :  (f :   ) {xs ys : List }  xs  ys  map f xs  map f ys
lem₃ = map⁺

lem₄ : IsCommutativeMonoid {A = List } _↭_ _++_ []
lem₄ = ++-isCommutativeMonoid

-- Alternatively permutations using non-propositional equality can be
-- found in:

import Data.List.Relation.Binary.Permutation.Setoid