DPutils-0.1.1.0: lib/DP/Backtraced/Core.hs
-- | The base constructors for generic backtracing.
--
-- NOTE this currently can capture dot-bracket notation, but not deep
-- semantics.
module DP.Backtraced.Core where
import Control.Lens
import Data.Foldable
import GHC.Generics (Generic)
import qualified Data.Sequence as Seq
import qualified Test.QuickCheck as QC
import qualified Test.SmallCheck.Series as SC
-- | This is a bit like a lazy "Data.Sequence" in terms of constructors. We can
-- not be spine-strict, otherwise we'd use @Data.Sequence@ and enjoy the better
-- performance.
data Backtraced ty where
-- | This backtrace is done
Epsilon ∷ Backtraced ty
-- | Expand a backtrace to the left. This is lazy, since backtracing relies
-- on laziness.
Cons ∷ ty → Backtraced ty → Backtraced ty
-- | Expand lazily to the right.
Snoc ∷ Backtraced ty → ty → Backtraced ty
-- | concatenate two structures
Append ∷ Backtraced ty → Backtraced ty → Backtraced ty
deriving (Eq,Ord,Show,Read,Generic,Functor,Foldable,Traversable)
-- | This is somewhat tricky, since we might have to walk down the structure
-- quite a bit and shuffle constructors without changing the actual leaf order.
instance Cons (Backtraced ty) (Backtraced ty') ty ty' where
{-# Inlinable _Cons #-}
_Cons =
let go1 Epsilon = Left Epsilon
go1 (Cons x xs) = Right (x,xs)
go1 (Snoc xs x) = go2 xs (Left x)
go1 (Append xs ys) = go2 xs (Right ys)
go2 Epsilon (Left y) = Right (y,Epsilon)
go2 Epsilon (Right ys) = go1 ys
go2 (Cons x xs) (Left y) = Right (x,Snoc xs y)
go2 (Cons x xs) (Right ys) = Right (x, Append xs ys)
go2 (Snoc xs x) (Left y) = go2 xs (Right $ x `Cons` Epsilon `Snoc` y)
go2 (Snoc xs x) (Right ys) = go2 xs (Right $ x `Cons` ys)
go2 (Append xs ys) (Left z) = go2 xs (Right $ ys `Snoc` z)
go2 (Append xs ys) (Right zs) = go2 xs (Right $ ys `Append` zs)
in prism (uncurry Cons) go1
instance Snoc (Backtraced ty) (Backtraced ty') ty ty' where
{-# Inlinable _Snoc #-}
_Snoc =
let go1 Epsilon = Left Epsilon
go1 (Cons x xs) = go2 (Left x) xs
go1 (Snoc xs x) = Right (xs,x)
go1 (Append xs ys) = go2 (Right xs) ys
go2 (Left x) Epsilon = Right (Epsilon,x)
go2 (Right xs) Epsilon = go1 xs
go2 (Left x) (Cons y ys) = go2 (Right $ x `Cons` (y `Cons` Epsilon)) ys
go2 (Right xs) (Cons y ys) = go2 (Right $ xs `Snoc` y) ys
go2 (Left x) (Snoc ys y) = Right (x `Cons` ys, y)
go2 (Right xs) (Snoc ys y) = Right (xs `Append` ys, y)
go2 (Left x) (Append ys zs) = go2 (Right $ x `Cons` ys) zs
go2 (Right xs) (Append ys zs) = go2 (Right $ xs `Append` ys) zs
in prism (uncurry Snoc) go1
(<|) = Cons
(|>) = Snoc
(><) = Append
infixr 5 <|
infixr 5 ><
infixl 5 |>
instance SC.Serial m a ⇒ SC.Serial m (Backtraced a)