{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeFamilies #-}
module GHC.Cmm.Dataflow.Block
    ( Extensibility (..)
    , O
    , C
    , MaybeO(..)
    , IndexedCO
    , Block(..)
    , blockAppend
    , blockCons
    , blockFromList
    , blockJoin
    , blockJoinHead
    , blockJoinTail
    , blockSnoc
    , blockSplit
    , blockSplitHead
    , blockSplitTail
    , blockToList
    , emptyBlock
    , firstNode
    , foldBlockNodesB
    , foldBlockNodesB3
    , foldBlockNodesF
    , isEmptyBlock
    , lastNode
    , mapBlock
    , mapBlock'
    , mapBlock3'
    , replaceFirstNode
    , replaceLastNode
    ) where

import GHC.Prelude

-- -----------------------------------------------------------------------------
-- Shapes: Open and Closed

-- | Used at the type level to indicate "open" vs "closed" structure.
data Extensibility
  -- | An "open" structure with a unique, unnamed control-flow edge flowing in
  -- or out. \"Fallthrough\" and concatenation are permitted at an open point.
  = Open
  -- | A "closed" structure which supports control transfer only through the use
  -- of named labels---no "fallthrough" is permitted. The number of control-flow
  -- edges is unconstrained.
  | Closed

type O = 'Open
type C = 'Closed

-- | Either type indexed by closed/open using type families
type family IndexedCO (ex :: Extensibility) (a :: k) (b :: k) :: k
type instance IndexedCO C a _b = a
type instance IndexedCO O _a b = b

-- | Maybe type indexed by open/closed
data MaybeO ex t where
  JustO    :: t -> MaybeO O t
  NothingO ::      MaybeO C t

deriving instance Functor (MaybeO ex)

-- -----------------------------------------------------------------------------
-- The Block type

-- | A sequence of nodes.  May be any of four shapes (O/O, O/C, C/O, C/C).
-- Open at the entry means single entry, mutatis mutandis for exit.
-- A closed/closed block is a /basic/ block and can't be extended further.
-- Clients should avoid manipulating blocks and should stick to either nodes
-- or graphs.
data Block n e x where
  BlockCO  :: n C O -> Block n O O          -> Block n C O
  BlockCC  :: n C O -> Block n O O -> n O C -> Block n C C
  BlockOC  ::          Block n O O -> n O C -> Block n O C

  BNil    :: Block n O O
  BMiddle :: n O O                      -> Block n O O
  BCat    :: Block n O O -> Block n O O -> Block n O O
  BSnoc   :: Block n O O -> n O O       -> Block n O O
  BCons   :: n O O       -> Block n O O -> Block n O O


-- -----------------------------------------------------------------------------
-- Simple operations on Blocks

-- Predicates

isEmptyBlock :: Block n e x -> Bool
isEmptyBlock :: forall (n :: Extensibility -> Extensibility -> *)
       (e :: Extensibility) (x :: Extensibility).
Block n e x -> Bool
isEmptyBlock Block n e x
BNil       = Bool
True
isEmptyBlock (BCat Block n 'Open 'Open
l Block n 'Open 'Open
r) = Block n 'Open 'Open -> Bool
forall (n :: Extensibility -> Extensibility -> *)
       (e :: Extensibility) (x :: Extensibility).
Block n e x -> Bool
isEmptyBlock Block n 'Open 'Open
l Bool -> Bool -> Bool
&& Block n 'Open 'Open -> Bool
forall (n :: Extensibility -> Extensibility -> *)
       (e :: Extensibility) (x :: Extensibility).
Block n e x -> Bool
isEmptyBlock Block n 'Open 'Open
r
isEmptyBlock Block n e x
_          = Bool
False


-- Building

emptyBlock :: Block n O O
emptyBlock :: forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open
emptyBlock = Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open
BNil

blockCons :: n O O -> Block n O x -> Block n O x
blockCons :: forall (n :: Extensibility -> Extensibility -> *)
       (x :: Extensibility).
n 'Open 'Open -> Block n 'Open x -> Block n 'Open x
blockCons n 'Open 'Open
n Block n 'Open x
b = case Block n 'Open x
b of
  BlockOC Block n 'Open 'Open
b n 'Open 'Closed
l  -> (Block n 'Open 'Open -> n 'Open 'Closed -> Block n 'Open x
Block n 'Open 'Open -> n 'Open 'Closed -> Block n 'Open 'Closed
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> n 'Open 'Closed -> Block n 'Open 'Closed
BlockOC (Block n 'Open 'Open -> n 'Open 'Closed -> Block n 'Open x)
-> Block n 'Open 'Open -> n 'Open 'Closed -> Block n 'Open x
forall a b. (a -> b) -> a -> b
$! (n 'Open 'Open
n n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *)
       (x :: Extensibility).
n 'Open 'Open -> Block n 'Open x -> Block n 'Open x
`blockCons` Block n 'Open 'Open
b)) n 'Open 'Closed
l
  BNil{}    -> n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
n 'Open 'Open -> Block n 'Open 'Open
BMiddle n 'Open 'Open
n
  BMiddle{} -> n 'Open 'Open
n n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
`BCons` Block n 'Open x
Block n 'Open 'Open
b
  BCat{}    -> n 'Open 'Open
n n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
`BCons` Block n 'Open x
Block n 'Open 'Open
b
  BSnoc{}   -> n 'Open 'Open
n n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
`BCons` Block n 'Open x
Block n 'Open 'Open
b
  BCons{}   -> n 'Open 'Open
n n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
`BCons` Block n 'Open x
Block n 'Open 'Open
b

blockSnoc :: Block n e O -> n O O -> Block n e O
blockSnoc :: forall (n :: Extensibility -> Extensibility -> *)
       (e :: Extensibility).
Block n e 'Open -> n 'Open 'Open -> Block n e 'Open
blockSnoc Block n e 'Open
b n 'Open 'Open
n = case Block n e 'Open
b of
  BlockCO n 'Closed 'Open
f Block n 'Open 'Open
b -> n 'Closed 'Open -> Block n 'Open 'Open -> Block n 'Closed 'Open
forall (n :: Extensibility -> Extensibility -> *).
n 'Closed 'Open -> Block n 'Open 'Open -> Block n 'Closed 'Open
BlockCO n 'Closed 'Open
f (Block n 'Open 'Open -> Block n e 'Open)
-> Block n 'Open 'Open -> Block n e 'Open
forall a b. (a -> b) -> a -> b
$! (Block n 'Open 'Open
b Block n 'Open 'Open -> n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *)
       (e :: Extensibility).
Block n e 'Open -> n 'Open 'Open -> Block n e 'Open
`blockSnoc` n 'Open 'Open
n)
  BNil{}      -> n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
n 'Open 'Open -> Block n 'Open 'Open
BMiddle n 'Open 'Open
n
  BMiddle{}   -> Block n e 'Open
Block n 'Open 'Open
b Block n 'Open 'Open -> n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> n 'Open 'Open -> Block n 'Open 'Open
`BSnoc` n 'Open 'Open
n
  BCat{}      -> Block n e 'Open
Block n 'Open 'Open
b Block n 'Open 'Open -> n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> n 'Open 'Open -> Block n 'Open 'Open
`BSnoc` n 'Open 'Open
n
  BSnoc{}     -> Block n e 'Open
Block n 'Open 'Open
b Block n 'Open 'Open -> n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> n 'Open 'Open -> Block n 'Open 'Open
`BSnoc` n 'Open 'Open
n
  BCons{}     -> Block n e 'Open
Block n 'Open 'Open
b Block n 'Open 'Open -> n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> n 'Open 'Open -> Block n 'Open 'Open
`BSnoc` n 'Open 'Open
n

blockJoinHead :: n C O -> Block n O x -> Block n C x
blockJoinHead :: forall (n :: Extensibility -> Extensibility -> *)
       (x :: Extensibility).
n 'Closed 'Open -> Block n 'Open x -> Block n 'Closed x
blockJoinHead n 'Closed 'Open
f (BlockOC Block n 'Open 'Open
b n 'Open 'Closed
l) = n 'Closed 'Open
-> Block n 'Open 'Open
-> n 'Open 'Closed
-> Block n 'Closed 'Closed
forall (n :: Extensibility -> Extensibility -> *).
n 'Closed 'Open
-> Block n 'Open 'Open
-> n 'Open 'Closed
-> Block n 'Closed 'Closed
BlockCC n 'Closed 'Open
f Block n 'Open 'Open
b n 'Open 'Closed
l
blockJoinHead n 'Closed 'Open
f Block n 'Open x
b = n 'Closed 'Open -> Block n 'Open 'Open -> Block n 'Closed 'Open
forall (n :: Extensibility -> Extensibility -> *).
n 'Closed 'Open -> Block n 'Open 'Open -> Block n 'Closed 'Open
BlockCO n 'Closed 'Open
f Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open
BNil Block n 'Closed 'Open -> Block n 'Open x -> Block n 'Closed x
forall (n :: Extensibility -> Extensibility -> *)
       (e :: Extensibility) (x :: Extensibility).
Block n e 'Open -> Block n 'Open x -> Block n e x
`cat` Block n 'Open x
b

blockJoinTail :: Block n e O -> n O C -> Block n e C
blockJoinTail :: forall (n :: Extensibility -> Extensibility -> *)
       (e :: Extensibility).
Block n e 'Open -> n 'Open 'Closed -> Block n e 'Closed
blockJoinTail (BlockCO n 'Closed 'Open
f Block n 'Open 'Open
b) n 'Open 'Closed
t = n 'Closed 'Open
-> Block n 'Open 'Open
-> n 'Open 'Closed
-> Block n 'Closed 'Closed
forall (n :: Extensibility -> Extensibility -> *).
n 'Closed 'Open
-> Block n 'Open 'Open
-> n 'Open 'Closed
-> Block n 'Closed 'Closed
BlockCC n 'Closed 'Open
f Block n 'Open 'Open
b n 'Open 'Closed
t
blockJoinTail Block n e 'Open
b n 'Open 'Closed
t = Block n e 'Open
b Block n e 'Open -> Block n 'Open 'Closed -> Block n e 'Closed
forall (n :: Extensibility -> Extensibility -> *)
       (e :: Extensibility) (x :: Extensibility).
Block n e 'Open -> Block n 'Open x -> Block n e x
`cat` Block n 'Open 'Open -> n 'Open 'Closed -> Block n 'Open 'Closed
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> n 'Open 'Closed -> Block n 'Open 'Closed
BlockOC Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open
BNil n 'Open 'Closed
t

blockJoin :: n C O -> Block n O O -> n O C -> Block n C C
blockJoin :: forall (n :: Extensibility -> Extensibility -> *).
n 'Closed 'Open
-> Block n 'Open 'Open
-> n 'Open 'Closed
-> Block n 'Closed 'Closed
blockJoin n 'Closed 'Open
f Block n 'Open 'Open
b n 'Open 'Closed
t = n 'Closed 'Open
-> Block n 'Open 'Open
-> n 'Open 'Closed
-> Block n 'Closed 'Closed
forall (n :: Extensibility -> Extensibility -> *).
n 'Closed 'Open
-> Block n 'Open 'Open
-> n 'Open 'Closed
-> Block n 'Closed 'Closed
BlockCC n 'Closed 'Open
f Block n 'Open 'Open
b n 'Open 'Closed
t

blockAppend :: Block n e O -> Block n O x -> Block n e x
blockAppend :: forall (n :: Extensibility -> Extensibility -> *)
       (e :: Extensibility) (x :: Extensibility).
Block n e 'Open -> Block n 'Open x -> Block n e x
blockAppend = Block n e 'Open -> Block n 'Open x -> Block n e x
forall (n :: Extensibility -> Extensibility -> *)
       (e :: Extensibility) (x :: Extensibility).
Block n e 'Open -> Block n 'Open x -> Block n e x
cat


-- Taking apart

firstNode :: Block n C x -> n C O
firstNode :: forall (n :: Extensibility -> Extensibility -> *)
       (x :: Extensibility).
Block n 'Closed x -> n 'Closed 'Open
firstNode (BlockCO n 'Closed 'Open
n Block n 'Open 'Open
_)   = n 'Closed 'Open
n
firstNode (BlockCC n 'Closed 'Open
n Block n 'Open 'Open
_ n 'Open 'Closed
_) = n 'Closed 'Open
n

lastNode :: Block n x C -> n O C
lastNode :: forall (n :: Extensibility -> Extensibility -> *)
       (x :: Extensibility).
Block n x 'Closed -> n 'Open 'Closed
lastNode (BlockOC   Block n 'Open 'Open
_ n 'Open 'Closed
n) = n 'Open 'Closed
n
lastNode (BlockCC n 'Closed 'Open
_ Block n 'Open 'Open
_ n 'Open 'Closed
n) = n 'Open 'Closed
n

blockSplitHead :: Block n C x -> (n C O, Block n O x)
blockSplitHead :: forall (n :: Extensibility -> Extensibility -> *)
       (x :: Extensibility).
Block n 'Closed x -> (n 'Closed 'Open, Block n 'Open x)
blockSplitHead (BlockCO n 'Closed 'Open
n Block n 'Open 'Open
b)   = (n 'Closed 'Open
n, Block n 'Open x
Block n 'Open 'Open
b)
blockSplitHead (BlockCC n 'Closed 'Open
n Block n 'Open 'Open
b n 'Open 'Closed
t) = (n 'Closed 'Open
n, Block n 'Open 'Open -> n 'Open 'Closed -> Block n 'Open 'Closed
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> n 'Open 'Closed -> Block n 'Open 'Closed
BlockOC Block n 'Open 'Open
b n 'Open 'Closed
t)

blockSplitTail :: Block n e C -> (Block n e O, n O C)
blockSplitTail :: forall (n :: Extensibility -> Extensibility -> *)
       (e :: Extensibility).
Block n e 'Closed -> (Block n e 'Open, n 'Open 'Closed)
blockSplitTail (BlockOC Block n 'Open 'Open
b n 'Open 'Closed
n)   = (Block n e 'Open
Block n 'Open 'Open
b, n 'Open 'Closed
n)
blockSplitTail (BlockCC n 'Closed 'Open
f Block n 'Open 'Open
b n 'Open 'Closed
t) = (n 'Closed 'Open -> Block n 'Open 'Open -> Block n 'Closed 'Open
forall (n :: Extensibility -> Extensibility -> *).
n 'Closed 'Open -> Block n 'Open 'Open -> Block n 'Closed 'Open
BlockCO n 'Closed 'Open
f Block n 'Open 'Open
b, n 'Open 'Closed
t)

-- | Split a closed block into its entry node, open middle block, and
-- exit node.
blockSplit :: Block n C C -> (n C O, Block n O O, n O C)
blockSplit :: forall (n :: Extensibility -> Extensibility -> *).
Block n 'Closed 'Closed
-> (n 'Closed 'Open, Block n 'Open 'Open, n 'Open 'Closed)
blockSplit (BlockCC n 'Closed 'Open
f Block n 'Open 'Open
b n 'Open 'Closed
t) = (n 'Closed 'Open
f, Block n 'Open 'Open
b, n 'Open 'Closed
t)

blockToList :: Block n O O -> [n O O]
blockToList :: forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> [n 'Open 'Open]
blockToList Block n 'Open 'Open
b = Block n 'Open 'Open -> [n 'Open 'Open] -> [n 'Open 'Open]
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> [n 'Open 'Open] -> [n 'Open 'Open]
go Block n 'Open 'Open
b []
   where go :: Block n O O -> [n O O] -> [n O O]
         go :: forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> [n 'Open 'Open] -> [n 'Open 'Open]
go Block n 'Open 'Open
BNil         [n 'Open 'Open]
r = [n 'Open 'Open]
r
         go (BMiddle n 'Open 'Open
n)  [n 'Open 'Open]
r = n 'Open 'Open
n n 'Open 'Open -> [n 'Open 'Open] -> [n 'Open 'Open]
forall a. a -> [a] -> [a]
: [n 'Open 'Open]
r
         go (BCat Block n 'Open 'Open
b1 Block n 'Open 'Open
b2) [n 'Open 'Open]
r = Block n 'Open 'Open -> [n 'Open 'Open] -> [n 'Open 'Open]
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> [n 'Open 'Open] -> [n 'Open 'Open]
go Block n 'Open 'Open
b1 ([n 'Open 'Open] -> [n 'Open 'Open])
-> [n 'Open 'Open] -> [n 'Open 'Open]
forall a b. (a -> b) -> a -> b
$! Block n 'Open 'Open -> [n 'Open 'Open] -> [n 'Open 'Open]
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> [n 'Open 'Open] -> [n 'Open 'Open]
go Block n 'Open 'Open
b2 [n 'Open 'Open]
r
         go (BSnoc Block n 'Open 'Open
b1 n 'Open 'Open
n) [n 'Open 'Open]
r = Block n 'Open 'Open -> [n 'Open 'Open] -> [n 'Open 'Open]
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> [n 'Open 'Open] -> [n 'Open 'Open]
go Block n 'Open 'Open
b1 (n 'Open 'Open
nn 'Open 'Open -> [n 'Open 'Open] -> [n 'Open 'Open]
forall a. a -> [a] -> [a]
:[n 'Open 'Open]
r)
         go (BCons n 'Open 'Open
n Block n 'Open 'Open
b1) [n 'Open 'Open]
r = n 'Open 'Open
n n 'Open 'Open -> [n 'Open 'Open] -> [n 'Open 'Open]
forall a. a -> [a] -> [a]
: Block n 'Open 'Open -> [n 'Open 'Open] -> [n 'Open 'Open]
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> [n 'Open 'Open] -> [n 'Open 'Open]
go Block n 'Open 'Open
b1 [n 'Open 'Open]
r

blockFromList :: [n O O] -> Block n O O
blockFromList :: forall (n :: Extensibility -> Extensibility -> *).
[n 'Open 'Open] -> Block n 'Open 'Open
blockFromList = (n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open)
-> Block n 'Open 'Open -> [n 'Open 'Open] -> Block n 'Open 'Open
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
BCons Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open
BNil

-- Modifying

replaceFirstNode :: Block n C x -> n C O -> Block n C x
replaceFirstNode :: forall (n :: Extensibility -> Extensibility -> *)
       (x :: Extensibility).
Block n 'Closed x -> n 'Closed 'Open -> Block n 'Closed x
replaceFirstNode (BlockCO n 'Closed 'Open
_ Block n 'Open 'Open
b)   n 'Closed 'Open
f = n 'Closed 'Open -> Block n 'Open 'Open -> Block n 'Closed 'Open
forall (n :: Extensibility -> Extensibility -> *).
n 'Closed 'Open -> Block n 'Open 'Open -> Block n 'Closed 'Open
BlockCO n 'Closed 'Open
f Block n 'Open 'Open
b
replaceFirstNode (BlockCC n 'Closed 'Open
_ Block n 'Open 'Open
b n 'Open 'Closed
n) n 'Closed 'Open
f = n 'Closed 'Open
-> Block n 'Open 'Open
-> n 'Open 'Closed
-> Block n 'Closed 'Closed
forall (n :: Extensibility -> Extensibility -> *).
n 'Closed 'Open
-> Block n 'Open 'Open
-> n 'Open 'Closed
-> Block n 'Closed 'Closed
BlockCC n 'Closed 'Open
f Block n 'Open 'Open
b n 'Open 'Closed
n

replaceLastNode :: Block n x C -> n O C -> Block n x C
replaceLastNode :: forall (n :: Extensibility -> Extensibility -> *)
       (x :: Extensibility).
Block n x 'Closed -> n 'Open 'Closed -> Block n x 'Closed
replaceLastNode (BlockOC   Block n 'Open 'Open
b n 'Open 'Closed
_) n 'Open 'Closed
n = Block n 'Open 'Open -> n 'Open 'Closed -> Block n 'Open 'Closed
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> n 'Open 'Closed -> Block n 'Open 'Closed
BlockOC Block n 'Open 'Open
b n 'Open 'Closed
n
replaceLastNode (BlockCC n 'Closed 'Open
l Block n 'Open 'Open
b n 'Open 'Closed
_) n 'Open 'Closed
n = n 'Closed 'Open
-> Block n 'Open 'Open
-> n 'Open 'Closed
-> Block n 'Closed 'Closed
forall (n :: Extensibility -> Extensibility -> *).
n 'Closed 'Open
-> Block n 'Open 'Open
-> n 'Open 'Closed
-> Block n 'Closed 'Closed
BlockCC n 'Closed 'Open
l Block n 'Open 'Open
b n 'Open 'Closed
n

-- -----------------------------------------------------------------------------
-- General concatenation

cat :: Block n e O -> Block n O x -> Block n e x
cat :: forall (n :: Extensibility -> Extensibility -> *)
       (e :: Extensibility) (x :: Extensibility).
Block n e 'Open -> Block n 'Open x -> Block n e x
cat Block n e 'Open
x Block n 'Open x
y = case Block n e 'Open
x of
  Block n e 'Open
BNil -> Block n e x
Block n 'Open x
y

  BlockCO n 'Closed 'Open
l Block n 'Open 'Open
b1 -> case Block n 'Open x
y of
                   BlockOC Block n 'Open 'Open
b2 n 'Open 'Closed
n -> (n 'Closed 'Open
-> Block n 'Open 'Open
-> n 'Open 'Closed
-> Block n 'Closed 'Closed
forall (n :: Extensibility -> Extensibility -> *).
n 'Closed 'Open
-> Block n 'Open 'Open
-> n 'Open 'Closed
-> Block n 'Closed 'Closed
BlockCC n 'Closed 'Open
l (Block n 'Open 'Open -> n 'Open 'Closed -> Block n e x)
-> Block n 'Open 'Open -> n 'Open 'Closed -> Block n e x
forall a b. (a -> b) -> a -> b
$! (Block n 'Open 'Open
b1 Block n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *)
       (e :: Extensibility) (x :: Extensibility).
Block n e 'Open -> Block n 'Open x -> Block n e x
`cat` Block n 'Open 'Open
b2)) n 'Open 'Closed
n
                   Block n 'Open x
BNil         -> Block n e x
Block n e 'Open
x
                   BMiddle n 'Open 'Open
_    -> n 'Closed 'Open -> Block n 'Open 'Open -> Block n 'Closed 'Open
forall (n :: Extensibility -> Extensibility -> *).
n 'Closed 'Open -> Block n 'Open 'Open -> Block n 'Closed 'Open
BlockCO n 'Closed 'Open
l (Block n 'Open 'Open -> Block n e x)
-> Block n 'Open 'Open -> Block n e x
forall a b. (a -> b) -> a -> b
$! (Block n 'Open 'Open
b1 Block n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *)
       (e :: Extensibility) (x :: Extensibility).
Block n e 'Open -> Block n 'Open x -> Block n e x
`cat` Block n 'Open x
Block n 'Open 'Open
y)
                   BCat{}       -> n 'Closed 'Open -> Block n 'Open 'Open -> Block n 'Closed 'Open
forall (n :: Extensibility -> Extensibility -> *).
n 'Closed 'Open -> Block n 'Open 'Open -> Block n 'Closed 'Open
BlockCO n 'Closed 'Open
l (Block n 'Open 'Open -> Block n e x)
-> Block n 'Open 'Open -> Block n e x
forall a b. (a -> b) -> a -> b
$! (Block n 'Open 'Open
b1 Block n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *)
       (e :: Extensibility) (x :: Extensibility).
Block n e 'Open -> Block n 'Open x -> Block n e x
`cat` Block n 'Open x
Block n 'Open 'Open
y)
                   BSnoc{}      -> n 'Closed 'Open -> Block n 'Open 'Open -> Block n 'Closed 'Open
forall (n :: Extensibility -> Extensibility -> *).
n 'Closed 'Open -> Block n 'Open 'Open -> Block n 'Closed 'Open
BlockCO n 'Closed 'Open
l (Block n 'Open 'Open -> Block n e x)
-> Block n 'Open 'Open -> Block n e x
forall a b. (a -> b) -> a -> b
$! (Block n 'Open 'Open
b1 Block n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *)
       (e :: Extensibility) (x :: Extensibility).
Block n e 'Open -> Block n 'Open x -> Block n e x
`cat` Block n 'Open x
Block n 'Open 'Open
y)
                   BCons{}      -> n 'Closed 'Open -> Block n 'Open 'Open -> Block n 'Closed 'Open
forall (n :: Extensibility -> Extensibility -> *).
n 'Closed 'Open -> Block n 'Open 'Open -> Block n 'Closed 'Open
BlockCO n 'Closed 'Open
l (Block n 'Open 'Open -> Block n e x)
-> Block n 'Open 'Open -> Block n e x
forall a b. (a -> b) -> a -> b
$! (Block n 'Open 'Open
b1 Block n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *)
       (e :: Extensibility) (x :: Extensibility).
Block n e 'Open -> Block n 'Open x -> Block n e x
`cat` Block n 'Open x
Block n 'Open 'Open
y)

  BMiddle n 'Open 'Open
n -> case Block n 'Open x
y of
                   BlockOC Block n 'Open 'Open
b2 n 'Open 'Closed
n2 -> (Block n 'Open 'Open -> n 'Open 'Closed -> Block n e x
Block n 'Open 'Open -> n 'Open 'Closed -> Block n 'Open 'Closed
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> n 'Open 'Closed -> Block n 'Open 'Closed
BlockOC (Block n 'Open 'Open -> n 'Open 'Closed -> Block n e x)
-> Block n 'Open 'Open -> n 'Open 'Closed -> Block n e x
forall a b. (a -> b) -> a -> b
$! (Block n e 'Open
Block n 'Open 'Open
x Block n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *)
       (e :: Extensibility) (x :: Extensibility).
Block n e 'Open -> Block n 'Open x -> Block n e x
`cat` Block n 'Open 'Open
b2)) n 'Open 'Closed
n2
                   Block n 'Open x
BNil          -> Block n e x
Block n e 'Open
x
                   BMiddle{}     -> n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
BCons n 'Open 'Open
n Block n 'Open x
Block n 'Open 'Open
y
                   BCat{}        -> n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
BCons n 'Open 'Open
n Block n 'Open x
Block n 'Open 'Open
y
                   BSnoc{}       -> n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
BCons n 'Open 'Open
n Block n 'Open x
Block n 'Open 'Open
y
                   BCons{}       -> n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
BCons n 'Open 'Open
n Block n 'Open x
Block n 'Open 'Open
y

  BCat{} -> case Block n 'Open x
y of
                   BlockOC Block n 'Open 'Open
b3 n 'Open 'Closed
n2 -> (Block n 'Open 'Open -> n 'Open 'Closed -> Block n e x
Block n 'Open 'Open -> n 'Open 'Closed -> Block n 'Open 'Closed
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> n 'Open 'Closed -> Block n 'Open 'Closed
BlockOC (Block n 'Open 'Open -> n 'Open 'Closed -> Block n e x)
-> Block n 'Open 'Open -> n 'Open 'Closed -> Block n e x
forall a b. (a -> b) -> a -> b
$! (Block n e 'Open
Block n 'Open 'Open
x Block n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *)
       (e :: Extensibility) (x :: Extensibility).
Block n e 'Open -> Block n 'Open x -> Block n e x
`cat` Block n 'Open 'Open
b3)) n 'Open 'Closed
n2
                   Block n 'Open x
BNil          -> Block n e x
Block n e 'Open
x
                   BMiddle n 'Open 'Open
n     -> Block n 'Open 'Open -> n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> n 'Open 'Open -> Block n 'Open 'Open
BSnoc Block n e 'Open
Block n 'Open 'Open
x n 'Open 'Open
n
                   BCat{}        -> Block n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
BCat Block n e 'Open
Block n 'Open 'Open
x Block n 'Open x
Block n 'Open 'Open
y
                   BSnoc{}       -> Block n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
BCat Block n e 'Open
Block n 'Open 'Open
x Block n 'Open x
Block n 'Open 'Open
y
                   BCons{}       -> Block n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
BCat Block n e 'Open
Block n 'Open 'Open
x Block n 'Open x
Block n 'Open 'Open
y

  BSnoc{} -> case Block n 'Open x
y of
                   BlockOC Block n 'Open 'Open
b2 n 'Open 'Closed
n2 -> (Block n 'Open 'Open -> n 'Open 'Closed -> Block n e x
Block n 'Open 'Open -> n 'Open 'Closed -> Block n 'Open 'Closed
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> n 'Open 'Closed -> Block n 'Open 'Closed
BlockOC (Block n 'Open 'Open -> n 'Open 'Closed -> Block n e x)
-> Block n 'Open 'Open -> n 'Open 'Closed -> Block n e x
forall a b. (a -> b) -> a -> b
$! (Block n e 'Open
Block n 'Open 'Open
x Block n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *)
       (e :: Extensibility) (x :: Extensibility).
Block n e 'Open -> Block n 'Open x -> Block n e x
`cat` Block n 'Open 'Open
b2)) n 'Open 'Closed
n2
                   Block n 'Open x
BNil          -> Block n e x
Block n e 'Open
x
                   BMiddle n 'Open 'Open
n     -> Block n 'Open 'Open -> n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> n 'Open 'Open -> Block n 'Open 'Open
BSnoc Block n e 'Open
Block n 'Open 'Open
x n 'Open 'Open
n
                   BCat{}        -> Block n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
BCat Block n e 'Open
Block n 'Open 'Open
x Block n 'Open x
Block n 'Open 'Open
y
                   BSnoc{}       -> Block n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
BCat Block n e 'Open
Block n 'Open 'Open
x Block n 'Open x
Block n 'Open 'Open
y
                   BCons{}       -> Block n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
BCat Block n e 'Open
Block n 'Open 'Open
x Block n 'Open x
Block n 'Open 'Open
y


  BCons{} -> case Block n 'Open x
y of
                   BlockOC Block n 'Open 'Open
b2 n 'Open 'Closed
n2 -> (Block n 'Open 'Open -> n 'Open 'Closed -> Block n e x
Block n 'Open 'Open -> n 'Open 'Closed -> Block n 'Open 'Closed
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> n 'Open 'Closed -> Block n 'Open 'Closed
BlockOC (Block n 'Open 'Open -> n 'Open 'Closed -> Block n e x)
-> Block n 'Open 'Open -> n 'Open 'Closed -> Block n e x
forall a b. (a -> b) -> a -> b
$! (Block n e 'Open
Block n 'Open 'Open
x Block n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *)
       (e :: Extensibility) (x :: Extensibility).
Block n e 'Open -> Block n 'Open x -> Block n e x
`cat` Block n 'Open 'Open
b2)) n 'Open 'Closed
n2
                   Block n 'Open x
BNil          -> Block n e x
Block n e 'Open
x
                   BMiddle n 'Open 'Open
n     -> Block n 'Open 'Open -> n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> n 'Open 'Open -> Block n 'Open 'Open
BSnoc Block n e 'Open
Block n 'Open 'Open
x n 'Open 'Open
n
                   BCat{}        -> Block n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
BCat Block n e 'Open
Block n 'Open 'Open
x Block n 'Open x
Block n 'Open 'Open
y
                   BSnoc{}       -> Block n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
BCat Block n e 'Open
Block n 'Open 'Open
x Block n 'Open x
Block n 'Open 'Open
y
                   BCons{}       -> Block n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
BCat Block n e 'Open
Block n 'Open 'Open
x Block n 'Open x
Block n 'Open 'Open
y


-- -----------------------------------------------------------------------------
-- Mapping

-- | map a function over the nodes of a 'Block'
mapBlock :: (forall e x. n e x -> n' e x) -> Block n e x -> Block n' e x
mapBlock :: forall (n :: Extensibility -> Extensibility -> *)
       (n' :: Extensibility -> Extensibility -> *) (e :: Extensibility)
       (x :: Extensibility).
(forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x)
-> Block n e x -> Block n' e x
mapBlock forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x
f (BlockCO n 'Closed 'Open
n Block n 'Open 'Open
b  ) = n' 'Closed 'Open -> Block n' 'Open 'Open -> Block n' 'Closed 'Open
forall (n :: Extensibility -> Extensibility -> *).
n 'Closed 'Open -> Block n 'Open 'Open -> Block n 'Closed 'Open
BlockCO (n 'Closed 'Open -> n' 'Closed 'Open
forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x
f n 'Closed 'Open
n) ((forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x)
-> Block n 'Open 'Open -> Block n' 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *)
       (n' :: Extensibility -> Extensibility -> *) (e :: Extensibility)
       (x :: Extensibility).
(forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x)
-> Block n e x -> Block n' e x
mapBlock n e x -> n' e x
forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x
f Block n 'Open 'Open
b)
mapBlock forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x
f (BlockOC   Block n 'Open 'Open
b n 'Open 'Closed
n) = Block n' 'Open 'Open -> n' 'Open 'Closed -> Block n' 'Open 'Closed
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> n 'Open 'Closed -> Block n 'Open 'Closed
BlockOC       ((forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x)
-> Block n 'Open 'Open -> Block n' 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *)
       (n' :: Extensibility -> Extensibility -> *) (e :: Extensibility)
       (x :: Extensibility).
(forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x)
-> Block n e x -> Block n' e x
mapBlock n e x -> n' e x
forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x
f Block n 'Open 'Open
b) (n 'Open 'Closed -> n' 'Open 'Closed
forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x
f n 'Open 'Closed
n)
mapBlock forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x
f (BlockCC n 'Closed 'Open
n Block n 'Open 'Open
b n 'Open 'Closed
m) = n' 'Closed 'Open
-> Block n' 'Open 'Open
-> n' 'Open 'Closed
-> Block n' 'Closed 'Closed
forall (n :: Extensibility -> Extensibility -> *).
n 'Closed 'Open
-> Block n 'Open 'Open
-> n 'Open 'Closed
-> Block n 'Closed 'Closed
BlockCC (n 'Closed 'Open -> n' 'Closed 'Open
forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x
f n 'Closed 'Open
n) ((forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x)
-> Block n 'Open 'Open -> Block n' 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *)
       (n' :: Extensibility -> Extensibility -> *) (e :: Extensibility)
       (x :: Extensibility).
(forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x)
-> Block n e x -> Block n' e x
mapBlock n e x -> n' e x
forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x
f Block n 'Open 'Open
b) (n 'Open 'Closed -> n' 'Open 'Closed
forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x
f n 'Open 'Closed
m)
mapBlock forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x
_  Block n e x
BNil           = Block n' e x
Block n' 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open
BNil
mapBlock forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x
f (BMiddle n 'Open 'Open
n)     = n' 'Open 'Open -> Block n' 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
n 'Open 'Open -> Block n 'Open 'Open
BMiddle (n 'Open 'Open -> n' 'Open 'Open
forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x
f n 'Open 'Open
n)
mapBlock forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x
f (BCat Block n 'Open 'Open
b1 Block n 'Open 'Open
b2)    = Block n' 'Open 'Open
-> Block n' 'Open 'Open -> Block n' 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
BCat    ((forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x)
-> Block n 'Open 'Open -> Block n' 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *)
       (n' :: Extensibility -> Extensibility -> *) (e :: Extensibility)
       (x :: Extensibility).
(forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x)
-> Block n e x -> Block n' e x
mapBlock n e x -> n' e x
forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x
f Block n 'Open 'Open
b1) ((forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x)
-> Block n 'Open 'Open -> Block n' 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *)
       (n' :: Extensibility -> Extensibility -> *) (e :: Extensibility)
       (x :: Extensibility).
(forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x)
-> Block n e x -> Block n' e x
mapBlock n e x -> n' e x
forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x
f Block n 'Open 'Open
b2)
mapBlock forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x
f (BSnoc Block n 'Open 'Open
b n 'Open 'Open
n)     = Block n' 'Open 'Open -> n' 'Open 'Open -> Block n' 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> n 'Open 'Open -> Block n 'Open 'Open
BSnoc   ((forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x)
-> Block n 'Open 'Open -> Block n' 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *)
       (n' :: Extensibility -> Extensibility -> *) (e :: Extensibility)
       (x :: Extensibility).
(forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x)
-> Block n e x -> Block n' e x
mapBlock n e x -> n' e x
forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x
f Block n 'Open 'Open
b)  (n 'Open 'Open -> n' 'Open 'Open
forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x
f n 'Open 'Open
n)
mapBlock forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x
f (BCons n 'Open 'Open
n Block n 'Open 'Open
b)     = n' 'Open 'Open -> Block n' 'Open 'Open -> Block n' 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
BCons   (n 'Open 'Open -> n' 'Open 'Open
forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x
f n 'Open 'Open
n)  ((forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x)
-> Block n 'Open 'Open -> Block n' 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *)
       (n' :: Extensibility -> Extensibility -> *) (e :: Extensibility)
       (x :: Extensibility).
(forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x)
-> Block n e x -> Block n' e x
mapBlock n e x -> n' e x
forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x
f Block n 'Open 'Open
b)

-- | A strict 'mapBlock'
mapBlock' :: (forall e x. n e x -> n' e x) -> (Block n e x -> Block n' e x)
mapBlock' :: forall (n :: Extensibility -> Extensibility -> *)
       (n' :: Extensibility -> Extensibility -> *) (e :: Extensibility)
       (x :: Extensibility).
(forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x)
-> Block n e x -> Block n' e x
mapBlock' forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x
f = (n 'Closed 'Open -> n' 'Closed 'Open,
 n 'Open 'Open -> n' 'Open 'Open,
 n 'Open 'Closed -> n' 'Open 'Closed)
-> Block n e x -> Block n' e x
forall (n :: Extensibility -> Extensibility -> *)
       (n' :: Extensibility -> Extensibility -> *) (e :: Extensibility)
       (x :: Extensibility).
(n 'Closed 'Open -> n' 'Closed 'Open,
 n 'Open 'Open -> n' 'Open 'Open,
 n 'Open 'Closed -> n' 'Open 'Closed)
-> Block n e x -> Block n' e x
mapBlock3' (n 'Closed 'Open -> n' 'Closed 'Open
forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x
f, n 'Open 'Open -> n' 'Open 'Open
forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x
f, n 'Open 'Closed -> n' 'Open 'Closed
forall (e :: Extensibility) (x :: Extensibility). n e x -> n' e x
f)

-- | map over a block, with different functions to apply to first nodes,
-- middle nodes and last nodes respectively.  The map is strict.
--
mapBlock3' :: forall n n' e x .
             ( n C O -> n' C O
             , n O O -> n' O O,
               n O C -> n' O C)
          -> Block n e x -> Block n' e x
mapBlock3' :: forall (n :: Extensibility -> Extensibility -> *)
       (n' :: Extensibility -> Extensibility -> *) (e :: Extensibility)
       (x :: Extensibility).
(n 'Closed 'Open -> n' 'Closed 'Open,
 n 'Open 'Open -> n' 'Open 'Open,
 n 'Open 'Closed -> n' 'Open 'Closed)
-> Block n e x -> Block n' e x
mapBlock3' (n 'Closed 'Open -> n' 'Closed 'Open
f, n 'Open 'Open -> n' 'Open 'Open
m, n 'Open 'Closed -> n' 'Open 'Closed
l) Block n e x
b = Block n e x -> Block n' e x
forall (e :: Extensibility) (x :: Extensibility).
Block n e x -> Block n' e x
go Block n e x
b
  where go :: forall e x . Block n e x -> Block n' e x
        go :: forall (e :: Extensibility) (x :: Extensibility).
Block n e x -> Block n' e x
go (BlockOC Block n 'Open 'Open
b n 'Open 'Closed
y)   = (Block n' 'Open 'Open -> n' 'Open 'Closed -> Block n' e x
Block n' 'Open 'Open -> n' 'Open 'Closed -> Block n' 'Open 'Closed
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> n 'Open 'Closed -> Block n 'Open 'Closed
BlockOC (Block n' 'Open 'Open -> n' 'Open 'Closed -> Block n' e x)
-> Block n' 'Open 'Open -> n' 'Open 'Closed -> Block n' e x
forall a b. (a -> b) -> a -> b
$! Block n 'Open 'Open -> Block n' 'Open 'Open
forall (e :: Extensibility) (x :: Extensibility).
Block n e x -> Block n' e x
go Block n 'Open 'Open
b) (n' 'Open 'Closed -> Block n' e x)
-> n' 'Open 'Closed -> Block n' e x
forall a b. (a -> b) -> a -> b
$! n 'Open 'Closed -> n' 'Open 'Closed
l n 'Open 'Closed
y
        go (BlockCO n 'Closed 'Open
x Block n 'Open 'Open
b)   = (n' 'Closed 'Open -> Block n' 'Open 'Open -> Block n' e x
n' 'Closed 'Open -> Block n' 'Open 'Open -> Block n' 'Closed 'Open
forall (n :: Extensibility -> Extensibility -> *).
n 'Closed 'Open -> Block n 'Open 'Open -> Block n 'Closed 'Open
BlockCO (n' 'Closed 'Open -> Block n' 'Open 'Open -> Block n' e x)
-> n' 'Closed 'Open -> Block n' 'Open 'Open -> Block n' e x
forall a b. (a -> b) -> a -> b
$! n 'Closed 'Open -> n' 'Closed 'Open
f n 'Closed 'Open
x) (Block n' 'Open 'Open -> Block n' e x)
-> Block n' 'Open 'Open -> Block n' e x
forall a b. (a -> b) -> a -> b
$! (Block n 'Open 'Open -> Block n' 'Open 'Open
forall (e :: Extensibility) (x :: Extensibility).
Block n e x -> Block n' e x
go Block n 'Open 'Open
b)
        go (BlockCC n 'Closed 'Open
x Block n 'Open 'Open
b n 'Open 'Closed
y) = ((n' 'Closed 'Open
-> Block n' 'Open 'Open -> n' 'Open 'Closed -> Block n' e x
n' 'Closed 'Open
-> Block n' 'Open 'Open
-> n' 'Open 'Closed
-> Block n' 'Closed 'Closed
forall (n :: Extensibility -> Extensibility -> *).
n 'Closed 'Open
-> Block n 'Open 'Open
-> n 'Open 'Closed
-> Block n 'Closed 'Closed
BlockCC (n' 'Closed 'Open
 -> Block n' 'Open 'Open -> n' 'Open 'Closed -> Block n' e x)
-> n' 'Closed 'Open
-> Block n' 'Open 'Open
-> n' 'Open 'Closed
-> Block n' e x
forall a b. (a -> b) -> a -> b
$! n 'Closed 'Open -> n' 'Closed 'Open
f n 'Closed 'Open
x) (Block n' 'Open 'Open -> n' 'Open 'Closed -> Block n' e x)
-> Block n' 'Open 'Open -> n' 'Open 'Closed -> Block n' e x
forall a b. (a -> b) -> a -> b
$! Block n 'Open 'Open -> Block n' 'Open 'Open
forall (e :: Extensibility) (x :: Extensibility).
Block n e x -> Block n' e x
go Block n 'Open 'Open
b) (n' 'Open 'Closed -> Block n' e x)
-> n' 'Open 'Closed -> Block n' e x
forall a b. (a -> b) -> a -> b
$! (n 'Open 'Closed -> n' 'Open 'Closed
l n 'Open 'Closed
y)
        go Block n e x
BNil            = Block n' e x
Block n' 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open
BNil
        go (BMiddle n 'Open 'Open
n)     = n' 'Open 'Open -> Block n' e x
n' 'Open 'Open -> Block n' 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
n 'Open 'Open -> Block n 'Open 'Open
BMiddle (n' 'Open 'Open -> Block n' e x) -> n' 'Open 'Open -> Block n' e x
forall a b. (a -> b) -> a -> b
$! n 'Open 'Open -> n' 'Open 'Open
m n 'Open 'Open
n
        go (BCat Block n 'Open 'Open
x Block n 'Open 'Open
y)      = (Block n' 'Open 'Open -> Block n' 'Open 'Open -> Block n' e x
Block n' 'Open 'Open
-> Block n' 'Open 'Open -> Block n' 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
BCat (Block n' 'Open 'Open -> Block n' 'Open 'Open -> Block n' e x)
-> Block n' 'Open 'Open -> Block n' 'Open 'Open -> Block n' e x
forall a b. (a -> b) -> a -> b
$! Block n 'Open 'Open -> Block n' 'Open 'Open
forall (e :: Extensibility) (x :: Extensibility).
Block n e x -> Block n' e x
go Block n 'Open 'Open
x) (Block n' 'Open 'Open -> Block n' e x)
-> Block n' 'Open 'Open -> Block n' e x
forall a b. (a -> b) -> a -> b
$! (Block n 'Open 'Open -> Block n' 'Open 'Open
forall (e :: Extensibility) (x :: Extensibility).
Block n e x -> Block n' e x
go Block n 'Open 'Open
y)
        go (BSnoc Block n 'Open 'Open
x n 'Open 'Open
n)     = (Block n' 'Open 'Open -> n' 'Open 'Open -> Block n' e x
Block n' 'Open 'Open -> n' 'Open 'Open -> Block n' 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
Block n 'Open 'Open -> n 'Open 'Open -> Block n 'Open 'Open
BSnoc (Block n' 'Open 'Open -> n' 'Open 'Open -> Block n' e x)
-> Block n' 'Open 'Open -> n' 'Open 'Open -> Block n' e x
forall a b. (a -> b) -> a -> b
$! Block n 'Open 'Open -> Block n' 'Open 'Open
forall (e :: Extensibility) (x :: Extensibility).
Block n e x -> Block n' e x
go Block n 'Open 'Open
x) (n' 'Open 'Open -> Block n' e x) -> n' 'Open 'Open -> Block n' e x
forall a b. (a -> b) -> a -> b
$! (n 'Open 'Open -> n' 'Open 'Open
m n 'Open 'Open
n)
        go (BCons n 'Open 'Open
n Block n 'Open 'Open
x)     = (n' 'Open 'Open -> Block n' 'Open 'Open -> Block n' e x
n' 'Open 'Open -> Block n' 'Open 'Open -> Block n' 'Open 'Open
forall (n :: Extensibility -> Extensibility -> *).
n 'Open 'Open -> Block n 'Open 'Open -> Block n 'Open 'Open
BCons (n' 'Open 'Open -> Block n' 'Open 'Open -> Block n' e x)
-> n' 'Open 'Open -> Block n' 'Open 'Open -> Block n' e x
forall a b. (a -> b) -> a -> b
$! n 'Open 'Open -> n' 'Open 'Open
m n 'Open 'Open
n) (Block n' 'Open 'Open -> Block n' e x)
-> Block n' 'Open 'Open -> Block n' e x
forall a b. (a -> b) -> a -> b
$! (Block n 'Open 'Open -> Block n' 'Open 'Open
forall (e :: Extensibility) (x :: Extensibility).
Block n e x -> Block n' e x
go Block n 'Open 'Open
x)

-- -----------------------------------------------------------------------------
-- Folding


-- | Fold a function over every node in a block, forward or backward.
-- The fold function must be polymorphic in the shape of the nodes.
foldBlockNodesF3 :: forall n a b c .
                   ( n C O       -> a -> b
                   , n O O       -> b -> b
                   , n O C       -> b -> c)
                 -> (forall e x . Block n e x -> IndexedCO e a b -> IndexedCO x c b)
foldBlockNodesF  :: forall n a .
                    (forall e x . n e x       -> a -> a)
                 -> (forall e x . Block n e x -> IndexedCO e a a -> IndexedCO x a a)
foldBlockNodesB3 :: forall n a b c .
                   ( n C O       -> b -> c
                   , n O O       -> b -> b
                   , n O C       -> a -> b)
                 -> (forall e x . Block n e x -> IndexedCO x a b -> IndexedCO e c b)
foldBlockNodesB  :: forall n a .
                    (forall e x . n e x       -> a -> a)
                 -> (forall e x . Block n e x -> IndexedCO x a a -> IndexedCO e a a)

foldBlockNodesF3 :: forall (n :: Extensibility -> Extensibility -> *) a b c.
(n 'Closed 'Open -> a -> b, n 'Open 'Open -> b -> b,
 n 'Open 'Closed -> b -> c)
-> forall (e :: Extensibility) (x :: Extensibility).
   Block n e x -> IndexedCO e a b -> IndexedCO x c b
foldBlockNodesF3 (n 'Closed 'Open -> a -> b
ff, n 'Open 'Open -> b -> b
fm, n 'Open 'Closed -> b -> c
fl) = Block n e x -> IndexedCO e a b -> IndexedCO x c b
forall (e :: Extensibility) (x :: Extensibility).
Block n e x -> IndexedCO e a b -> IndexedCO x c b
block
  where block :: forall e x . Block n e x -> IndexedCO e a b -> IndexedCO x c b
        block :: forall (e :: Extensibility) (x :: Extensibility).
Block n e x -> IndexedCO e a b -> IndexedCO x c b
block (BlockCO n 'Closed 'Open
f Block n 'Open 'Open
b  )   = n 'Closed 'Open -> a -> b
ff n 'Closed 'Open
f (a -> b) -> (b -> b) -> a -> b
forall a b c. (a -> b) -> (b -> c) -> a -> c
`cat` Block n 'Open 'Open -> IndexedCO 'Open a b -> IndexedCO 'Open c b
forall (e :: Extensibility) (x :: Extensibility).
Block n e x -> IndexedCO e a b -> IndexedCO x c b
block Block n 'Open 'Open
b
        block (BlockCC n 'Closed 'Open
f Block n 'Open 'Open
b n 'Open 'Closed
l)   = n 'Closed 'Open -> a -> b
ff n 'Closed 'Open
f (a -> b) -> (b -> b) -> a -> b
forall a b c. (a -> b) -> (b -> c) -> a -> c
`cat` Block n 'Open 'Open -> IndexedCO 'Open a b -> IndexedCO 'Open c b
forall (e :: Extensibility) (x :: Extensibility).
Block n e x -> IndexedCO e a b -> IndexedCO x c b
block Block n 'Open 'Open
b (a -> b) -> (b -> c) -> a -> c
forall a b c. (a -> b) -> (b -> c) -> a -> c
`cat` n 'Open 'Closed -> b -> c
fl n 'Open 'Closed
l
        block (BlockOC   Block n 'Open 'Open
b n 'Open 'Closed
l)   =            Block n 'Open 'Open -> IndexedCO 'Open a b -> IndexedCO 'Open c b
forall (e :: Extensibility) (x :: Extensibility).
Block n e x -> IndexedCO e a b -> IndexedCO x c b
block Block n 'Open 'Open
b (b -> b) -> (b -> c) -> b -> c
forall a b c. (a -> b) -> (b -> c) -> a -> c
`cat` n 'Open 'Closed -> b -> c
fl n 'Open 'Closed
l
        block Block n e x
BNil              = b -> b
IndexedCO e a b -> IndexedCO x c b
forall a. a -> a
id
        block (BMiddle n 'Open 'Open
node)    = n 'Open 'Open -> b -> b
fm n 'Open 'Open
node
        block (Block n 'Open 'Open
b1 `BCat`    Block n 'Open 'Open
b2) = Block n 'Open 'Open -> IndexedCO 'Open a b -> IndexedCO 'Open c b
forall (e :: Extensibility) (x :: Extensibility).
Block n e x -> IndexedCO e a b -> IndexedCO x c b
block Block n 'Open 'Open
b1 (b -> b) -> (b -> b) -> b -> b
forall a b c. (a -> b) -> (b -> c) -> a -> c
`cat` Block n 'Open 'Open -> IndexedCO 'Open a b -> IndexedCO 'Open c b
forall (e :: Extensibility) (x :: Extensibility).
Block n e x -> IndexedCO e a b -> IndexedCO x c b
block Block n 'Open 'Open
b2
        block (Block n 'Open 'Open
b1 `BSnoc` n 'Open 'Open
n)    = Block n 'Open 'Open -> IndexedCO 'Open a b -> IndexedCO 'Open c b
forall (e :: Extensibility) (x :: Extensibility).
Block n e x -> IndexedCO e a b -> IndexedCO x c b
block Block n 'Open 'Open
b1 (b -> b) -> (b -> b) -> b -> b
forall a b c. (a -> b) -> (b -> c) -> a -> c
`cat` n 'Open 'Open -> b -> b
fm n 'Open 'Open
n
        block (n 'Open 'Open
n `BCons` Block n 'Open 'Open
b2)    = n 'Open 'Open -> b -> b
fm n 'Open 'Open
n (b -> b) -> (b -> b) -> b -> b
forall a b c. (a -> b) -> (b -> c) -> a -> c
`cat` Block n 'Open 'Open -> IndexedCO 'Open a b -> IndexedCO 'Open c b
forall (e :: Extensibility) (x :: Extensibility).
Block n e x -> IndexedCO e a b -> IndexedCO x c b
block Block n 'Open 'Open
b2
        cat :: forall a b c. (a -> b) -> (b -> c) -> a -> c
        cat :: forall a b c. (a -> b) -> (b -> c) -> a -> c
cat a -> b
f b -> c
f' = b -> c
f' (b -> c) -> (a -> b) -> a -> c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> b
f

foldBlockNodesF :: forall (n :: Extensibility -> Extensibility -> *) a.
(forall (e :: Extensibility) (x :: Extensibility). n e x -> a -> a)
-> forall (e :: Extensibility) (x :: Extensibility).
   Block n e x -> IndexedCO e a a -> IndexedCO x a a
foldBlockNodesF forall (e :: Extensibility) (x :: Extensibility). n e x -> a -> a
f = (n 'Closed 'Open -> a -> a, n 'Open 'Open -> a -> a,
 n 'Open 'Closed -> a -> a)
-> forall (e :: Extensibility) (x :: Extensibility).
   Block n e x -> IndexedCO e a a -> IndexedCO x a a
forall (n :: Extensibility -> Extensibility -> *) a b c.
(n 'Closed 'Open -> a -> b, n 'Open 'Open -> b -> b,
 n 'Open 'Closed -> b -> c)
-> forall (e :: Extensibility) (x :: Extensibility).
   Block n e x -> IndexedCO e a b -> IndexedCO x c b
foldBlockNodesF3 (n 'Closed 'Open -> a -> a
forall (e :: Extensibility) (x :: Extensibility). n e x -> a -> a
f, n 'Open 'Open -> a -> a
forall (e :: Extensibility) (x :: Extensibility). n e x -> a -> a
f, n 'Open 'Closed -> a -> a
forall (e :: Extensibility) (x :: Extensibility). n e x -> a -> a
f)

foldBlockNodesB3 :: forall (n :: Extensibility -> Extensibility -> *) a b c.
(n 'Closed 'Open -> b -> c, n 'Open 'Open -> b -> b,
 n 'Open 'Closed -> a -> b)
-> forall (e :: Extensibility) (x :: Extensibility).
   Block n e x -> IndexedCO x a b -> IndexedCO e c b
foldBlockNodesB3 (n 'Closed 'Open -> b -> c
ff, n 'Open 'Open -> b -> b
fm, n 'Open 'Closed -> a -> b
fl) = Block n e x -> IndexedCO x a b -> IndexedCO e c b
forall (e :: Extensibility) (x :: Extensibility).
Block n e x -> IndexedCO x a b -> IndexedCO e c b
block
  where block :: forall e x . Block n e x -> IndexedCO x a b -> IndexedCO e c b
        block :: forall (e :: Extensibility) (x :: Extensibility).
Block n e x -> IndexedCO x a b -> IndexedCO e c b
block (BlockCO n 'Closed 'Open
f Block n 'Open 'Open
b  )   = n 'Closed 'Open -> b -> c
ff n 'Closed 'Open
f (b -> c) -> (b -> b) -> b -> c
forall a b c. (b -> c) -> (a -> b) -> a -> c
`cat` Block n 'Open 'Open -> IndexedCO 'Open a b -> IndexedCO 'Open c b
forall (e :: Extensibility) (x :: Extensibility).
Block n e x -> IndexedCO x a b -> IndexedCO e c b
block Block n 'Open 'Open
b
        block (BlockCC n 'Closed 'Open
f Block n 'Open 'Open
b n 'Open 'Closed
l)   = n 'Closed 'Open -> b -> c
ff n 'Closed 'Open
f (b -> c) -> (b -> b) -> b -> c
forall a b c. (b -> c) -> (a -> b) -> a -> c
`cat` Block n 'Open 'Open -> IndexedCO 'Open a b -> IndexedCO 'Open c b
forall (e :: Extensibility) (x :: Extensibility).
Block n e x -> IndexedCO x a b -> IndexedCO e c b
block Block n 'Open 'Open
b (b -> c) -> (a -> b) -> a -> c
forall a b c. (b -> c) -> (a -> b) -> a -> c
`cat` n 'Open 'Closed -> a -> b
fl n 'Open 'Closed
l
        block (BlockOC   Block n 'Open 'Open
b n 'Open 'Closed
l)   =            Block n 'Open 'Open -> IndexedCO 'Open a b -> IndexedCO 'Open c b
forall (e :: Extensibility) (x :: Extensibility).
Block n e x -> IndexedCO x a b -> IndexedCO e c b
block Block n 'Open 'Open
b (b -> b) -> (a -> b) -> a -> b
forall a b c. (b -> c) -> (a -> b) -> a -> c
`cat` n 'Open 'Closed -> a -> b
fl n 'Open 'Closed
l
        block Block n e x
BNil              = b -> b
IndexedCO x a b -> IndexedCO e c b
forall a. a -> a
id
        block (BMiddle n 'Open 'Open
node)    = n 'Open 'Open -> b -> b
fm n 'Open 'Open
node
        block (Block n 'Open 'Open
b1 `BCat`    Block n 'Open 'Open
b2) = Block n 'Open 'Open -> IndexedCO 'Open a b -> IndexedCO 'Open c b
forall (e :: Extensibility) (x :: Extensibility).
Block n e x -> IndexedCO x a b -> IndexedCO e c b
block Block n 'Open 'Open
b1 (b -> b) -> (b -> b) -> b -> b
forall a b c. (b -> c) -> (a -> b) -> a -> c
`cat` Block n 'Open 'Open -> IndexedCO 'Open a b -> IndexedCO 'Open c b
forall (e :: Extensibility) (x :: Extensibility).
Block n e x -> IndexedCO x a b -> IndexedCO e c b
block Block n 'Open 'Open
b2
        block (Block n 'Open 'Open
b1 `BSnoc` n 'Open 'Open
n)    = Block n 'Open 'Open -> IndexedCO 'Open a b -> IndexedCO 'Open c b
forall (e :: Extensibility) (x :: Extensibility).
Block n e x -> IndexedCO x a b -> IndexedCO e c b
block Block n 'Open 'Open
b1 (b -> b) -> (b -> b) -> b -> b
forall a b c. (b -> c) -> (a -> b) -> a -> c
`cat` n 'Open 'Open -> b -> b
fm n 'Open 'Open
n
        block (n 'Open 'Open
n `BCons` Block n 'Open 'Open
b2)    = n 'Open 'Open -> b -> b
fm n 'Open 'Open
n (b -> b) -> (b -> b) -> b -> b
forall a b c. (b -> c) -> (a -> b) -> a -> c
`cat` Block n 'Open 'Open -> IndexedCO 'Open a b -> IndexedCO 'Open c b
forall (e :: Extensibility) (x :: Extensibility).
Block n e x -> IndexedCO x a b -> IndexedCO e c b
block Block n 'Open 'Open
b2
        cat :: forall a b c. (b -> c) -> (a -> b) -> a -> c
        cat :: forall a b c. (b -> c) -> (a -> b) -> a -> c
cat b -> c
f a -> b
f' = b -> c
f (b -> c) -> (a -> b) -> a -> c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> b
f'

foldBlockNodesB :: forall (n :: Extensibility -> Extensibility -> *) a.
(forall (e :: Extensibility) (x :: Extensibility). n e x -> a -> a)
-> forall (e :: Extensibility) (x :: Extensibility).
   Block n e x -> IndexedCO x a a -> IndexedCO e a a
foldBlockNodesB forall (e :: Extensibility) (x :: Extensibility). n e x -> a -> a
f = (n 'Closed 'Open -> a -> a, n 'Open 'Open -> a -> a,
 n 'Open 'Closed -> a -> a)
-> forall (e :: Extensibility) (x :: Extensibility).
   Block n e x -> IndexedCO x a a -> IndexedCO e a a
forall (n :: Extensibility -> Extensibility -> *) a b c.
(n 'Closed 'Open -> b -> c, n 'Open 'Open -> b -> b,
 n 'Open 'Closed -> a -> b)
-> forall (e :: Extensibility) (x :: Extensibility).
   Block n e x -> IndexedCO x a b -> IndexedCO e c b
foldBlockNodesB3 (n 'Closed 'Open -> a -> a
forall (e :: Extensibility) (x :: Extensibility). n e x -> a -> a
f, n 'Open 'Open -> a -> a
forall (e :: Extensibility) (x :: Extensibility). n e x -> a -> a
f, n 'Open 'Closed -> a -> a
forall (e :: Extensibility) (x :: Extensibility). n e x -> a -> a
f)