module Free.Agent.Derivation
( Derivation (..),
derivation,
valid,
chaseLog,
)
where
import Circuit.Agent (Post (..))
import Data.List (genericIndex)
data Derivation a = Derivation
{ forall a. Derivation a -> Post a
dPost :: Post a,
forall a. Derivation a -> [Post a]
dParents :: [Post a]
}
deriving (Int -> Derivation a -> ShowS
[Derivation a] -> ShowS
Derivation a -> String
(Int -> Derivation a -> ShowS)
-> (Derivation a -> String)
-> ([Derivation a] -> ShowS)
-> Show (Derivation a)
forall a. Show a => Int -> Derivation a -> ShowS
forall a. Show a => [Derivation a] -> ShowS
forall a. Show a => Derivation a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> Derivation a -> ShowS
showsPrec :: Int -> Derivation a -> ShowS
$cshow :: forall a. Show a => Derivation a -> String
show :: Derivation a -> String
$cshowList :: forall a. Show a => [Derivation a] -> ShowS
showList :: [Derivation a] -> ShowS
Show, Derivation a -> Derivation a -> Bool
(Derivation a -> Derivation a -> Bool)
-> (Derivation a -> Derivation a -> Bool) -> Eq (Derivation a)
forall a. Eq a => Derivation a -> Derivation a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a. Eq a => Derivation a -> Derivation a -> Bool
== :: Derivation a -> Derivation a -> Bool
$c/= :: forall a. Eq a => Derivation a -> Derivation a -> Bool
/= :: Derivation a -> Derivation a -> Bool
Eq)
derivation :: [Post a] -> Post a -> Derivation a
derivation :: forall a. [Post a] -> Post a -> Derivation a
derivation [Post a]
prior Post a
p =
Post a -> [Post a] -> Derivation a
forall a. Post a -> [Post a] -> Derivation a
Derivation
Post a
p
[ [Post a]
prior [Post a] -> PostId -> Post a
forall i a. Integral i => [a] -> i -> a
`genericIndex` PostId
i
| PostId
i <- Post a -> [PostId]
forall a. Post a -> [PostId]
thread Post a
p
]
valid :: [Post a] -> Post a -> Bool
valid :: forall a. [Post a] -> Post a -> Bool
valid [Post a]
prior Post a
p = (PostId -> Bool) -> [PostId] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (PostId -> PostId -> Bool
forall a. Ord a => a -> a -> Bool
< Int -> PostId
forall a b. (Integral a, Num b) => a -> b
fromIntegral ([Post a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Post a]
prior)) (Post a -> [PostId]
forall a. Post a -> [PostId]
thread Post a
p)
chaseLog :: (Eq a) => [Post a] -> [Post a]
chaseLog :: forall a. Eq a => [Post a] -> [Post a]
chaseLog [] = []
chaseLog [Post a]
posts = [Post a] -> [Post a] -> [Post a]
go [] [[Post a] -> Post a
forall a. HasCallStack => [a] -> a
last [Post a]
posts]
where
priorOf :: Post a -> [Post a]
priorOf Post a
p = (Post a -> Bool) -> [Post a] -> [Post a]
forall a. (a -> Bool) -> [a] -> [a]
takeWhile (Post a -> Post a -> Bool
forall a. Eq a => a -> a -> Bool
/= Post a
p) [Post a]
posts
go :: [Post a] -> [Post a] -> [Post a]
go [Post a]
acc [] = [Post a]
acc
go [Post a]
acc (Post a
p : [Post a]
ps)
| Post a
p Post a -> [Post a] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Post a]
acc = [Post a] -> [Post a] -> [Post a]
go [Post a]
acc [Post a]
ps
| Bool
otherwise = [Post a] -> [Post a] -> [Post a]
go (Post a
p Post a -> [Post a] -> [Post a]
forall a. a -> [a] -> [a]
: [Post a]
acc) (Derivation a -> [Post a]
forall a. Derivation a -> [Post a]
dParents ([Post a] -> Post a -> Derivation a
forall a. [Post a] -> Post a -> Derivation a
derivation (Post a -> [Post a]
priorOf Post a
p) Post a
p) [Post a] -> [Post a] -> [Post a]
forall a. [a] -> [a] -> [a]
++ [Post a]
ps)