zsyntax-0.2.0.0: src/Otter/SearchRes.hs
{-# LANGUAGE DeriveFunctor #-}
module Otter.SearchRes
( SearchRes
, Res(..)
, Extraction(..)
, FailureReason(..)
, extractResults
, delay
, cons
) where
import Data.List.NonEmpty (NonEmpty(..))
data Res a = Res a | Delay deriving (Functor)
-- | Type representing the result of proof search. Every element in the list
-- corresponds to the result of analysing node in the search space by the search
-- algorithm. The result is 'Res' in the positive case the node is a goal node,
-- or 'Delay' in the negative case.
--
-- The search agorithm produces an element of `'SearchRes' a` lazily, inserting
-- 'Delay' constructors to ensure that the computation is productive even in the
-- case no goal node is found in the search space. This allows to perform proof
-- search in an on-demand fashion, possibly giving up after a certain number of
-- 'Delay's.
type SearchRes a = [Res a]
-- | Delays a search result stream.
--
-- @
-- delay x == Delay : x
-- @
delay :: SearchRes a -> SearchRes a
delay = (Delay :)
-- | Appends a result to a search result stream.
--
-- @
-- cons x y = Res x : y
-- @
cons :: a -> SearchRes a -> SearchRes a
cons x = (Res x :)
-- | Type of reasons why no result can be extracted from a search result stream.
--
-- Either the search space has been exhaustively searched and no result was
-- found (the query is not a theorem), or the search was terminated preemptively
-- according to an upper bound imposed on the maximum depth of the search space.
data FailureReason = NotATheorem | SpaceTooBig
-- | Type of the result of 'extractResults', which extracts all positive search
-- results from a search result stream.
-- An element of `Extraction a` is either a non-empty list of positive results,
-- or an element of 'SpaceExhausted' giving a reason why no result was found.
data Extraction a = AllResults (NonEmpty a) | NoResults FailureReason
resListUntil :: Int -> SearchRes a -> ([a], FailureReason)
resListUntil _ [] = ([], NotATheorem)
resListUntil 0 (_ : _) = ([], SpaceTooBig)
resListUntil i (Res x : xs) = let (ys, b) = resListUntil i xs in (x : ys, b)
resListUntil i (Delay : xs) = resListUntil (i - 1) xs
-- | Extract all the positive results from a search result stream, stopping if
-- no result is found after the given number of delays.
extractResults :: Int -> SearchRes a -> Extraction a
extractResults i res = case resListUntil i res of
([], b) -> NoResults b
(x : xs, _) -> AllResults (x :| xs)