module Data.Functor.Holey
(
Holey
, HoleF(..)
, pattern Hole
, pattern Existing
, whole
, plug
, punch
) where
import Data.Functor.Foldable (Fix(..), unfix, fold, unfold)
import Data.Functor.Decomposed
data HoleF f t
= HoleF
| ExistingF (f t)
deriving (Eq, Ord, Functor)
pattern Hole = Fix HoleF
pattern Existing e = Fix (ExistingF e)
instance Decomposed HoleF where
fmap1 _ HoleF = HoleF
fmap1 f (ExistingF e) = ExistingF (f e)
type family Holey f
type instance Holey (Fix f) = Fix (HoleF f)
whole :: Functor f => Fix f -> Fix (HoleF f)
whole = unfold (ExistingF . unfix)
plug :: Functor f => Fix f -> Fix (HoleF f) -> Fix f
plug x = fold phi
where
phi HoleF = x
phi (ExistingF e) = Fix e
punch :: Functor f => (Fix f -> Bool) -> Fix f -> Fix (HoleF f)
punch test = unfold phi
where
phi x@(Fix e) = if test x then HoleF else ExistingF e