idris-1.3.0: libs/contrib/Data/Chain.idr
module Data.Chain
import Data.Vect
import Control.Isomorphism
%default total
%access public export
||| Repeated function application
Chain : Nat -> (i, o : Type) -> Type
Chain Z _ o = o
Chain (S k) i o = i -> Chain k i o
||| Repeated endofunction application
EndoChain : Nat -> Type -> Type
EndoChain n t = Chain n t t
||| (.) generalized to any number of arguments.
after : (o -> o') -> (Chain n i o) -> (Chain n i o')
after {n=Z} f x = f x
after {n=S k} f fs = after f . fs
||| `on` generalized to any number of arguments
before : (i -> i') -> (Chain n i' o) -> (Chain n i o)
before {n=Z} _ x = x
before {n=S k} f fs = (f `before`) . (fs . f)
||| Fill in the same argument for all items (available for a single argument as
||| Data.Combinators.reflex)
reflexes : (Chain n i o) -> (i -> o)
reflexes {n=Z} x _ = x
reflexes {n=S k} fs y = reflexes (fs y) y
||| Create a vect of a given length from the arguments given.
packVect : Chain n i (Vect n i)
packVect {n=Z} = []
packVect {n=S k} = (`after` packVect) . Data.Vect.(::)
-- For some reason we get a can't disambiguate name: Prelude.List.::,
-- Prelude.Stream.::, Data.Vect.:: if we leave out the Data.Vect specification
||| Apply a function over a vector to our new type
fromVectFunc : (Vect n i -> o) -> (Chain n i o)
fromVectFunc f = (f `after` packVect)
withIso : Iso t t' -> EndoChain n t -> EndoChain n t'
withIso (MkIso to from _ _) = (from `before`) . (to `after`)