{- |
Copyright   :  (c) Henning Thielemann 2007

Maintainer  :  haskell@henning-thielemann.de
Stability   :  stable
Portability :  Haskell 98

Lists of elements of alternating type.
This module iuses custom data types which depend mutually.
This looks nicer but it lacks high level optimizations.
(They could be added, though.)
-}
module Data.AlternatingList.Custom where

infixr 5 :>, :<

{- |
A list of elements of alternating types,
where the types of the beginning and the end element are independent,
namely @a@ at the beginning, @b@ at the end.

Example:
@1 :> \'a\' :< 2 :> \'b\' :< End@
-}
data Disparate a b =
    a :> Uniform a b
  | End

{- |
A list of elements of alternating types,
where the type of the beginning and the end element is equal,
namely @b@.

Example:
@1 :> \'a\' :< 2 :> \'b\' :< 3 :> End@
-}
data Uniform a b =
    b :< Disparate a b



mapDisparate ::
   (a0 -> a1) -> (b0 -> b1) ->
   (Disparate a0 b0 -> Disparate a1 b1)
mapDisparate :: forall a0 a1 b0 b1.
(a0 -> a1) -> (b0 -> b1) -> Disparate a0 b0 -> Disparate a1 b1
mapDisparate a0 -> a1
f b0 -> b1
g =
   (a0 -> Uniform a1 b1 -> Disparate a1 b1)
-> (b0 -> Disparate a1 b1 -> Uniform a1 b1)
-> Disparate a1 b1
-> Disparate a0 b0
-> Disparate a1 b1
forall a c d b.
(a -> c -> d) -> (b -> d -> c) -> d -> Disparate a b -> d
foldrDisparate (a1 -> Uniform a1 b1 -> Disparate a1 b1
forall a b. a -> Uniform a b -> Disparate a b
(:>) (a1 -> Uniform a1 b1 -> Disparate a1 b1)
-> (a0 -> a1) -> a0 -> Uniform a1 b1 -> Disparate a1 b1
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a0 -> a1
f) (b1 -> Disparate a1 b1 -> Uniform a1 b1
forall a b. b -> Disparate a b -> Uniform a b
(:<) (b1 -> Disparate a1 b1 -> Uniform a1 b1)
-> (b0 -> b1) -> b0 -> Disparate a1 b1 -> Uniform a1 b1
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b0 -> b1
g) Disparate a1 b1
forall a b. Disparate a b
End

mapUniform ::
   (a0 -> a1) -> (b0 -> b1) ->
   (Uniform a0 b0 -> Uniform a1 b1)
mapUniform :: forall a0 a1 b0 b1.
(a0 -> a1) -> (b0 -> b1) -> Uniform a0 b0 -> Uniform a1 b1
mapUniform a0 -> a1
f b0 -> b1
g =
   (a0 -> Uniform a1 b1 -> Disparate a1 b1)
-> (b0 -> Disparate a1 b1 -> Uniform a1 b1)
-> Disparate a1 b1
-> Uniform a0 b0
-> Uniform a1 b1
forall a c d b.
(a -> c -> d) -> (b -> d -> c) -> d -> Uniform a b -> c
foldrUniform (a1 -> Uniform a1 b1 -> Disparate a1 b1
forall a b. a -> Uniform a b -> Disparate a b
(:>) (a1 -> Uniform a1 b1 -> Disparate a1 b1)
-> (a0 -> a1) -> a0 -> Uniform a1 b1 -> Disparate a1 b1
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a0 -> a1
f) (b1 -> Disparate a1 b1 -> Uniform a1 b1
forall a b. b -> Disparate a b -> Uniform a b
(:<) (b1 -> Disparate a1 b1 -> Uniform a1 b1)
-> (b0 -> b1) -> b0 -> Disparate a1 b1 -> Uniform a1 b1
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b0 -> b1
g) Disparate a1 b1
forall a b. Disparate a b
End



foldrDisparate ::
   (a -> c -> d) -> (b -> d -> c) ->
   d -> Disparate a b -> d
foldrDisparate :: forall a c d b.
(a -> c -> d) -> (b -> d -> c) -> d -> Disparate a b -> d
foldrDisparate a -> c -> d
f b -> d -> c
g d
start Disparate a b
a0 =
   case Disparate a b
a0 of
      Disparate a b
End -> d
start
      a
a :> Uniform a b
bas -> a -> c -> d
f a
a ((a -> c -> d) -> (b -> d -> c) -> d -> Uniform a b -> c
forall a c d b.
(a -> c -> d) -> (b -> d -> c) -> d -> Uniform a b -> c
foldrUniform a -> c -> d
f b -> d -> c
g d
start Uniform a b
bas)

foldrUniform ::
   (a -> c -> d) -> (b -> d -> c) ->
   d -> Uniform a b -> c
foldrUniform :: forall a c d b.
(a -> c -> d) -> (b -> d -> c) -> d -> Uniform a b -> c
foldrUniform a -> c -> d
f b -> d -> c
g d
start (b
b :< Disparate a b
abas) =
   b -> d -> c
g b
b ((a -> c -> d) -> (b -> d -> c) -> d -> Disparate a b -> d
forall a c d b.
(a -> c -> d) -> (b -> d -> c) -> d -> Disparate a b -> d
foldrDisparate a -> c -> d
f b -> d -> c
g d
start Disparate a b
abas)