```{- |
Maps that handle pairs of amplitudes and sampled values.
They are a special form of arrows.
-}
module Synthesizer.Dimensional.Map where

{-
import qualified Number.DimensionTerm        as DN
import qualified Algebra.DimensionTerm       as Dim
-}

import qualified Data.Tuple as Tuple
import Data.Tuple.HT as TupleHT (swap, )

import Prelude hiding (map, id, fst, snd, )

{- |
This type shall ensure, that you do not accidentally
bring amplitudes and the corresponding low-level signal values out of sync.
We also use it for generation of internal control parameters
in "Synthesizer.Dimensional.Causal.ControlledProcess".
In principle this could also be 'Causal.T',
but maps are not bound to a sampling rate,
and thus do not need the @s@ type parameter.
-}
newtype T amp0 amp1 yv0 yv1 =
Cons (amp0 -> (amp1, yv0 -> yv1))

independent ::
(amp0 -> amp1) -> (yv0 -> yv1) ->
T amp0 amp1 yv0 yv1
independent f g =
Cons (\amp -> (f amp, g))

double ::
T amp (amp, amp)
y (y, y)
double =
let aux = \x -> (x, x)
in  independent aux aux

fst ::
T (amp0,amp1) amp0
(y0,y1) y0
fst =
let aux = Tuple.fst
in  independent aux aux

snd ::
T (amp0,amp1) amp1
(y0,y1) y1
snd =
let aux = Tuple.snd
in  independent aux aux

swap ::
T (amp0,amp1) (amp1,amp0)
(y0,y1) (y1,y0)
swap =
let aux = TupleHT.swap
in  independent aux aux

balanceRight ::
T ((amp0,amp1), amp2) (amp0, (amp1,amp2))
((y0,y1), y2) (y0, (y1,y2))
balanceRight =
let aux = \((a,b), c) -> (a, (b,c))
in  independent aux aux

balanceLeft ::
T (amp0, (amp1,amp2)) ((amp0,amp1), amp2)
(y0, (y1,y2)) ((y0,y1), y2)
balanceLeft =
let aux = \(a, (b,c)) -> ((a,b), c)
in  independent aux aux

packTriple ::
T (amp0,(amp1,amp2)) (amp0,amp1,amp2)
(y0,(y1,y2)) (y0,y1,y2)
packTriple =
let aux = \(a,(b,c)) -> (a,b,c)
in  independent aux aux

unpackTriple ::
T (amp0,amp1,amp2) (amp0,(amp1,amp2))
(y0,y1,y2) (y0,(y1,y2))
unpackTriple =
let aux = \(a,b,c) -> (a,(b,c))
in  independent aux aux
```