> module Kulitta.QuotientSpaces where
> import Data.List
> import System.Random
> import Control.DeepSeq
> import Data.Maybe


> type EqClass a = [a] -- equivalence class

> type QSpace a = [EqClass a] -- quotient space

> type Predicate a = a -> Bool
> type Norm a = a -> a -- normalizations

> type EqRel a = a -> a -> Bool -- equivalence relations


========= QUOTIENT SPACE IMPLEMENTATION =========

First we define the "slash" operator for S/R.

> (//) :: (Eq a) => [a] -> EqRel a -> QSpace a
> [] // r = []
> xs // r =
>     let sx = [y | y <- xs, r y (head xs)]
>     in  sx : [z | z <- xs, not (elem z sx)] // r

The eqClass function is used to find the equivalence class of an
element, x, given a quotient space and the relation used to form it.
We need to know the relation used, because we do not require that
x is in the quotient space, qs.

> eqClass :: (Eq a, Show a) => QSpace a -> EqRel a -> a -> EqClass a
> eqClass qs r x =
>     let ind = findIndex (\e -> r x (head e)) qs
>     in  maybe (error ("(eqClass) No class for "++show x)) (qs !!) ind

=============================

Code for randomizing a list.

> randomize :: StdGen -> [a] -> [a]
> randomize sg rs =
>     let n = length rs
>         plist = take n (nub (randomRs (0,n-1) sg))
>     in  map (rs!!) plist