{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TupleSections #-}

-- | Implement and execute relational programs.
module Kanren.Goal (
  -- * The Goal monad
  Goal,
  run,

  -- * Primitive operations
  successo,
  failo,
  (===),
  conj,
  conjMany,
  disj,
  disjMany,
  conde,
  delay,

  -- * Constraints
  (=/=),

  -- * Fresh variables
  Fresh (..),
  fresh,
) where

import Control.Applicative (Alternative (..))
import Control.Monad (ap)
import qualified Data.Foldable as Foldable

import Kanren.Core
import qualified Kanren.Core as Core
import Kanren.Stream

infix 4 ===, =/=
infixr 3 `conj`
infixr 2 `disj`

-- $setup
-- >>> :set -package typedKanren
-- >>> instance Logical Int
-- >>> instance Logical Bool
-- >>> import Kanren.LogicalBase

-- | A computation in the relational world.
--
-- On its own, a goal performs search in a search tree. It takes some state and
-- transforms it to a stream of new states. But it is better to think of a goal
-- as a relational program. If you want to write a predicate, it will take
-- 'Term's as parameters and return a 'Goal'.
--
-- > zeroo :: Term Int -> Goal ()
-- > zeroo x = x === Value 0
--
-- A 'Goal' is a 'Monad', so you can use the do-notation to write relations.
--
-- > oppositeso :: Term Bool -> Term Bool -> Goal ()
-- > oppositeso x y = do
-- >   x === Value True
-- >   y === Value False
--
-- Sequencing two goals performs 'conj'unction. To make a branch, use
-- 'disj'unction.
--
-- > noto :: Term Bool -> Term Bool -> Goal ()
-- > noto x y = xIsTrue `disj` xIsFalse
-- >  where
-- >   xIsTrue = x === Value True `conj` y === Value False
-- >   xIsFalse = x === Value False `conj` y === Value True
--
-- To execute a goal and find its solutions, use 'run'.
--
-- >>> run (\x -> noto (Value False) x)
-- [Value True]
newtype Goal x = Goal {forall x. Goal x -> State -> Stream (State, x)
runGoal :: State -> Stream (State, x)}

instance Functor Goal where
  fmap :: forall a b. (a -> b) -> Goal a -> Goal b
fmap a -> b
f (Goal State -> Stream (State, a)
g) = (State -> Stream (State, b)) -> Goal b
forall x. (State -> Stream (State, x)) -> Goal x
Goal ((Stream (State, a) -> Stream (State, b))
-> (State -> Stream (State, a)) -> State -> Stream (State, b)
forall a b. (a -> b) -> (State -> a) -> State -> b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (((State, a) -> (State, b))
-> Stream (State, a) -> Stream (State, b)
forall a b. (a -> b) -> Stream a -> Stream b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((a -> b) -> (State, a) -> (State, b)
forall a b. (a -> b) -> (State, a) -> (State, b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f)) State -> Stream (State, a)
g)

instance Applicative Goal where
  pure :: forall a. a -> Goal a
pure a
x = (State -> Stream (State, a)) -> Goal a
forall x. (State -> Stream (State, x)) -> Goal x
Goal (\State
s -> (State, a) -> Stream (State, a)
forall a. a -> Stream a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (State
s, a
x))
  <*> :: forall a b. Goal (a -> b) -> Goal a -> Goal b
(<*>) = Goal (a -> b) -> Goal a -> Goal b
forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
ap

instance Monad Goal where
  return :: forall a. a -> Goal a
return = a -> Goal a
forall a. a -> Goal a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
  >> :: forall a b. Goal a -> Goal b -> Goal b
(>>) = Goal a -> Goal b -> Goal b
forall a b. Goal a -> Goal b -> Goal b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
(*>)
  Goal State -> Stream (State, a)
g1 >>= :: forall a b. Goal a -> (a -> Goal b) -> Goal b
>>= a -> Goal b
f = (State -> Stream (State, b)) -> Goal b
forall x. (State -> Stream (State, x)) -> Goal x
Goal ((State -> Stream (State, b)) -> Goal b)
-> (State -> Stream (State, b)) -> Goal b
forall a b. (a -> b) -> a -> b
$ \State
s -> do
    (State
s', a
x) <- State -> Stream (State, a)
g1 State
s
    Goal b -> State -> Stream (State, b)
forall x. Goal x -> State -> Stream (State, x)
runGoal (a -> Goal b
f a
x) State
s'

instance Alternative Goal where
  empty :: forall a. Goal a
empty = Goal a
forall a. Goal a
failo
  <|> :: forall a. Goal a -> Goal a -> Goal a
(<|>) = Goal a -> Goal a -> Goal a
forall a. Goal a -> Goal a -> Goal a
disj

-- | Query for solutions of a goal.
--
-- >>> run (\x -> x === Value (42 :: Int))
-- [42]
--
-- You can ask to solve for several variables, or none at all. You can still
-- create intermediate variables inside using 'fresh', but they will not be
-- returned as solutions.
--
-- >>> run (\() -> fresh >>= (\x -> x === Value True))
-- [()]
--
-- Note that there may be several solutions, including infinitely many or zero.
-- If you want to limit the number of solutions, just put it through 'take'.
--
-- >>> take 5 $ run (\x -> disjMany (map (\a -> x === Value a) [0 :: Int ..]))
-- [0,1,2,3,4]
--
-- This function will return logical representation of solutions. This matters
-- for complex types which have a separate logical representation. If you want
-- to transform them back to regular representation, use 'fmap' and 'extract''.
--
-- >>> extract' <$> run (\x -> x === inject' [True])
-- [Just [True]]
--
-- Note that the retrived solutions might be subject to constraints, but it is
-- not yet possible to retrieve them.
run :: (Fresh v) => (v -> Goal ()) -> [v]
run :: forall v. Fresh v => (v -> Goal ()) -> [v]
run v -> Goal ()
f = Stream v -> [v]
forall a. Stream a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
Foldable.toList Stream v
solutions
 where
  states :: Stream (State, v)
states = (Goal v -> State -> Stream (State, v))
-> State -> Goal v -> Stream (State, v)
forall a b c. (a -> b -> c) -> b -> a -> c
flip Goal v -> State -> Stream (State, v)
forall x. Goal x -> State -> Stream (State, x)
runGoal State
Core.empty (Goal v -> Stream (State, v)) -> Goal v -> Stream (State, v)
forall a b. (a -> b) -> a -> b
$ do
    v
vars <- Goal v
forall v. Fresh v => Goal v
fresh
    v -> Goal ()
f v
vars
    v -> Goal v
forall a. a -> Goal a
forall (f :: * -> *) a. Applicative f => a -> f a
pure v
vars
  solutions :: Stream v
solutions = ((State, v) -> v) -> Stream (State, v) -> Stream v
forall a b. (a -> b) -> Stream a -> Stream b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((State -> v -> v) -> (State, v) -> v
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry State -> v -> v
forall v. Fresh v => State -> v -> v
resolve) Stream (State, v)
states

-- | A goal that always succeeds.
--
-- >>> run (\() -> successo ())
-- [()]
successo :: x -> Goal x
successo :: forall a. a -> Goal a
successo = x -> Goal x
forall a. a -> Goal a
forall (f :: * -> *) a. Applicative f => a -> f a
pure

-- | A goal that always fails.
--
-- >>> run (\() -> failo)
-- []
failo :: Goal x
failo :: forall a. Goal a
failo = (State -> Stream (State, x)) -> Goal x
forall x. (State -> Stream (State, x)) -> Goal x
Goal (Stream (State, x) -> State -> Stream (State, x)
forall a b. a -> b -> a
const Stream (State, x)
forall a. Stream a
Done)

-- | Unify two terms.
--
-- >>> run (\() -> Value 42 === Value (42 :: Int))
-- [()]
-- >>> run (\() -> Value 42 === Value (37 :: Int))
-- []
(===) :: (Logical a) => Term a -> Term a -> Goal ()
Term a
a === :: forall a. Logical a => Term a -> Term a -> Goal ()
=== Term a
b = (State -> Stream (State, ())) -> Goal ()
forall x. (State -> Stream (State, x)) -> Goal x
Goal (Maybe (State, ()) -> Stream (State, ())
forall a. Maybe a -> Stream a
maybeToStream (Maybe (State, ()) -> Stream (State, ()))
-> (State -> Maybe (State, ())) -> State -> Stream (State, ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (State -> (State, ())) -> Maybe State -> Maybe (State, ())
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (,()) (Maybe State -> Maybe (State, ()))
-> (State -> Maybe State) -> State -> Maybe (State, ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Term a -> Term a -> State -> Maybe State
forall a. Logical a => Term a -> Term a -> State -> Maybe State
unify' Term a
a Term a
b)

-- | Put a constraint that two terms must not be equal.
--
-- >>> run (\x -> x =/= Value 42 `conj` x === Value (37 :: Int))
-- [37]
-- >>> run (\x -> x =/= Value 42 `conj` x === Value (42 :: Int))
-- []
--
-- It is not yet possible to retrieve solutions along with remaining constraints.
(=/=) :: (Logical a) => Term a -> Term a -> Goal ()
Term a
a =/= :: forall a. Logical a => Term a -> Term a -> Goal ()
=/= Term a
b = (State -> Stream (State, ())) -> Goal ()
forall x. (State -> Stream (State, x)) -> Goal x
Goal (Maybe (State, ()) -> Stream (State, ())
forall a. Maybe a -> Stream a
maybeToStream (Maybe (State, ()) -> Stream (State, ()))
-> (State -> Maybe (State, ())) -> State -> Stream (State, ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (State -> (State, ())) -> Maybe State -> Maybe (State, ())
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (,()) (Maybe State -> Maybe (State, ()))
-> (State -> Maybe State) -> State -> Maybe (State, ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Term a -> Term a -> State -> Maybe State
forall a. Logical a => Term a -> Term a -> State -> Maybe State
disequality Term a
a Term a
b)

-- | Perform conjnction of two goals. If the first goal succeeds, run the second
-- goal on its results.
--
-- >>> run (\x -> x === Value 42 `conj` x === Value (42 :: Int))
-- [42]
-- >>> run (\x -> x === Value 42 `conj` x === Value (37 :: Int))
-- []
-- >>> run (\(x, y) -> x === Value (42 :: Int) `conj` y === Value True)
-- [(42,True)]
--
-- Note that the do-notation performs conjunction as well, so you will rarely
-- need to use this function directly.
--
-- >>> :{
--  run (\(x, y) -> do
--    x === Value (42 :: Int)
--    y === Value True
--  )
-- :}
-- [(42,True)]
conj :: Goal x -> Goal y -> Goal y
conj :: forall a b. Goal a -> Goal b -> Goal b
conj = Goal x -> Goal y -> Goal y
forall a b. Goal a -> Goal b -> Goal b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
(>>)

-- | Perform conjunction of several goals, left to right.
--
-- >>> run (\(x, y) -> conjMany [x === Value (42 :: Int), y === Value True])
-- [(42,True)]
conjMany :: [Goal ()] -> Goal ()
conjMany :: [Goal ()] -> Goal ()
conjMany = (Goal () -> Goal () -> Goal ()) -> Goal () -> [Goal ()] -> Goal ()
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Goal () -> Goal () -> Goal ()
forall a b. Goal a -> Goal b -> Goal b
conj (() -> Goal ()
forall a. a -> Goal a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ())

-- | Perform disjunction of two goals. Run the first goal, then the second, and
-- combine their results.
--
-- >>> run (\x -> x === Value 42 `disj` x === Value (37 :: Int))
-- [42,37]
-- >>> run (\x -> x === Value 42 `disj` x === Value (42 :: Int))
-- [42,42]
-- >>> run (\(x, y) -> x === Value (42 :: Int) `disj` y === Value True)
-- [(42,_.0),(_.1,True)]
disj :: Goal x -> Goal x -> Goal x
disj :: forall a. Goal a -> Goal a -> Goal a
disj Goal x
left Goal x
right = Goal x -> Goal x
forall a. Goal a -> Goal a
delay (Goal x -> Goal x -> Goal x
forall a. Goal a -> Goal a -> Goal a
unsafeDisjunction Goal x
left Goal x
right)

-- | Perform disjunction of several goals, left to right.
--
-- >>> run (\x -> disjMany (map (\a -> x === Value a) [1, 3 .. 11 :: Int]))
-- [1,3,5,7,9,11]
disjMany :: [Goal x] -> Goal x
disjMany :: forall x. [Goal x] -> Goal x
disjMany = Goal x -> Goal x
forall a. Goal a -> Goal a
delay (Goal x -> Goal x) -> ([Goal x] -> Goal x) -> [Goal x] -> Goal x
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Goal x] -> Goal x
forall x. [Goal x] -> Goal x
go
 where
  go :: [Goal x] -> Goal x
go [] = Goal x
forall a. Goal a
failo
  go [Goal x
x] = Goal x
x
  go (Goal x
x : xs :: [Goal x]
xs@(Goal x
_ : [Goal x]
_)) = Goal x -> Goal x -> Goal x
forall a. Goal a -> Goal a -> Goal a
unsafeDisjunction Goal x
x ([Goal x] -> Goal x
go [Goal x]
xs)

-- | Consider several possible cases, using syntax similar to @conde@ from
-- @faster-minikanren@.
--
-- >>> :{
--   run (\(x, y) -> conde
--     [ [ x === Value False, y === Value 0 ]
--     , [ x === Value True, y === Value 1 ]
--     ])
-- :}
-- [(False,0),(True,1)]
--
-- However, this might not be the best syntax for Haskell. Using 'disjMany' with
-- the do-notation may be easier to type and less noisy:
--
-- >>> :{
--   run (\(x, y) -> disjMany
--     [ do
--         x === Value False
--         y === Value 0
--     , do
--         x === Value True
--         y === Value 1
--     ])
-- :}
-- [(False,0),(True,1)]
--
-- In addition, the "Match" module provides pattern matching over variants,
-- which might better express your intent.
--
-- >>> :{
--   run (\(x, y) -> x & (matche
--     & on _False (\() -> y === Value 0)
--     & on _True (\() -> y === Value 1)))
-- :}
-- [(False,0),(True,1)]
conde :: [[Goal ()]] -> Goal ()
conde :: [[Goal ()]] -> Goal ()
conde = [Goal ()] -> Goal ()
forall x. [Goal x] -> Goal x
disjMany ([Goal ()] -> Goal ())
-> ([[Goal ()]] -> [Goal ()]) -> [[Goal ()]] -> Goal ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Goal ()] -> Goal ()) -> [[Goal ()]] -> [Goal ()]
forall a b. (a -> b) -> [a] -> [b]
map [Goal ()] -> Goal ()
conjMany

-- | The existential quantifier.
--
-- Whenever you need an intermediate variable, 'fresh' will give you one.
--
-- >>> :{
--   run (\() -> do
--     x <- fresh
--     x === Value (42 :: Int))
-- :}
-- [()]
--
-- Creating a lot of variables one-by-one might be tiresome though. This is why
-- 'fresh' is not a standalone function but a method on a type class. 'Fresh'
-- is implemented not only for @'Term' a@ but for tuples too, so you can ask for
-- several fresh variables at once.
--
-- >>> :{
--   run (\() -> do
--     (x, y) <- fresh
--     x === Value True
--     y === Value False)
-- :}
-- [()]
--
-- In fact, 'run' also uses 'Fresh', so you can choose how many variables you
-- want to solve for.
--
-- >>> :{
--   run (\(x, y) -> do
--     x === Value True
--     y === Value False)
-- :}
-- [(True,False)]
--
-- As an edge case, you can ask for no variables at all using @()@. While this
-- is not useful inside relations, this is how the first two examples actually
-- work. 'Fresh' is also used for pattern matching from the @"Match"@ module
-- when the matched value is not known yet.
class Fresh v where
  -- | Create fresh variables.
  fresh' :: Goal v

  -- | Resolve each variable to its value in the given state.
  resolve :: State -> v -> v

fresh :: (Fresh v) => Goal v
fresh :: forall v. Fresh v => Goal v
fresh = Goal v -> Goal v
forall a. Goal a -> Goal a
delay Goal v
forall v. Fresh v => Goal v
fresh'

instance Fresh () where
  fresh' :: Goal ()
fresh' = () -> Goal ()
forall a. a -> Goal a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
  resolve :: State -> () -> ()
resolve State
_ () = ()

instance (Logical a) => Fresh (Term a) where
  fresh' :: Goal (Term a)
fresh' = (State -> Stream (State, Term a)) -> Goal (Term a)
forall x. (State -> Stream (State, x)) -> Goal x
Goal ((State, Term a) -> Stream (State, Term a)
forall a. a -> Stream a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((State, Term a) -> Stream (State, Term a))
-> (State -> (State, Term a)) -> State -> Stream (State, Term a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. State -> (State, Term a)
forall a. State -> (State, Term a)
makeVariable)
  resolve :: State -> Term a -> Term a
resolve = State -> Term a -> Term a
forall a. Logical a => State -> Term a -> Term a
walk'

instance (Fresh a, Fresh b) => Fresh (a, b) where
  fresh' :: Goal (a, b)
fresh' = do
    a
a <- Goal a
forall v. Fresh v => Goal v
fresh'
    b
b <- Goal b
forall v. Fresh v => Goal v
fresh'
    (a, b) -> Goal (a, b)
forall a. a -> Goal a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (a
a, b
b)
  resolve :: State -> (a, b) -> (a, b)
resolve State
state (a
a, b
b) = (a
a', b
b')
   where
    a' :: a
a' = State -> a -> a
forall v. Fresh v => State -> v -> v
resolve State
state a
a
    b' :: b
b' = State -> b -> b
forall v. Fresh v => State -> v -> v
resolve State
state b
b

instance (Fresh a, Fresh b, Fresh c) => Fresh (a, b, c) where
  fresh' :: Goal (a, b, c)
fresh' = do
    a
a <- Goal a
forall v. Fresh v => Goal v
fresh'
    (b
b, c
c) <- Goal (b, c)
forall v. Fresh v => Goal v
fresh'
    (a, b, c) -> Goal (a, b, c)
forall a. a -> Goal a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (a
a, b
b, c
c)
  resolve :: State -> (a, b, c) -> (a, b, c)
resolve State
state (a
a, b
b, c
c) = (a
a', b
b', c
c')
   where
    a' :: a
a' = State -> a -> a
forall v. Fresh v => State -> v -> v
resolve State
state a
a
    (b
b', c
c') = State -> (b, c) -> (b, c)
forall v. Fresh v => State -> v -> v
resolve State
state (b
b, c
c)

instance
  (Fresh a, Fresh b, Fresh c, Fresh d)
  => Fresh (a, b, c, d)
  where
  fresh' :: Goal (a, b, c, d)
fresh' = do
    a
a <- Goal a
forall v. Fresh v => Goal v
fresh'
    (b
b, c
c, d
d) <- Goal (b, c, d)
forall v. Fresh v => Goal v
fresh'
    (a, b, c, d) -> Goal (a, b, c, d)
forall a. a -> Goal a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (a
a, b
b, c
c, d
d)
  resolve :: State -> (a, b, c, d) -> (a, b, c, d)
resolve State
state (a
a, b
b, c
c, d
d) = (a
a', b
b', c
c', d
d')
   where
    a' :: a
a' = State -> a -> a
forall v. Fresh v => State -> v -> v
resolve State
state a
a
    (b
b', c
c', d
d') = State -> (b, c, d) -> (b, c, d)
forall v. Fresh v => State -> v -> v
resolve State
state (b
b, c
c, d
d)

instance
  (Fresh a, Fresh b, Fresh c, Fresh d, Fresh e)
  => Fresh (a, b, c, d, e)
  where
  fresh' :: Goal (a, b, c, d, e)
fresh' = do
    a
a <- Goal a
forall v. Fresh v => Goal v
fresh'
    (b
b, c
c, d
d, e
e) <- Goal (b, c, d, e)
forall v. Fresh v => Goal v
fresh'
    (a, b, c, d, e) -> Goal (a, b, c, d, e)
forall a. a -> Goal a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (a
a, b
b, c
c, d
d, e
e)
  resolve :: State -> (a, b, c, d, e) -> (a, b, c, d, e)
resolve State
state (a
a, b
b, c
c, d
d, e
e) = (a
a', b
b', c
c', d
d', e
e')
   where
    a' :: a
a' = State -> a -> a
forall v. Fresh v => State -> v -> v
resolve State
state a
a
    (b
b', c
c', d
d', e
e') = State -> (b, c, d, e) -> (b, c, d, e)
forall v. Fresh v => State -> v -> v
resolve State
state (b
b, c
c, d
d, e
e)

instance
  (Fresh a, Fresh b, Fresh c, Fresh d, Fresh e, Fresh f)
  => Fresh (a, b, c, d, e, f)
  where
  fresh' :: Goal (a, b, c, d, e, f)
fresh' = do
    a
a <- Goal a
forall v. Fresh v => Goal v
fresh'
    (b
b, c
c, d
d, e
e, f
f) <- Goal (b, c, d, e, f)
forall v. Fresh v => Goal v
fresh'
    (a, b, c, d, e, f) -> Goal (a, b, c, d, e, f)
forall a. a -> Goal a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (a
a, b
b, c
c, d
d, e
e, f
f)
  resolve :: State -> (a, b, c, d, e, f) -> (a, b, c, d, e, f)
resolve State
state (a
a, b
b, c
c, d
d, e
e, f
f) = (a
a', b
b', c
c', d
d', e
e', f
f')
   where
    a' :: a
a' = State -> a -> a
forall v. Fresh v => State -> v -> v
resolve State
state a
a
    (b
b', c
c', d
d', e
e', f
f') = State -> (b, c, d, e, f) -> (b, c, d, e, f)
forall v. Fresh v => State -> v -> v
resolve State
state (b
b, c
c, d
d, e
e, f
f)

delay :: Goal a -> Goal a
delay :: forall a. Goal a -> Goal a
delay (Goal State -> Stream (State, a)
g) = (State -> Stream (State, a)) -> Goal a
forall x. (State -> Stream (State, x)) -> Goal x
Goal (Stream (State, a) -> Stream (State, a)
forall a. Stream a -> Stream a
Await (Stream (State, a) -> Stream (State, a))
-> (State -> Stream (State, a)) -> State -> Stream (State, a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. State -> Stream (State, a)
g)

unsafeDisjunction :: Goal x -> Goal x -> Goal x
unsafeDisjunction :: forall a. Goal a -> Goal a -> Goal a
unsafeDisjunction (Goal State -> Stream (State, x)
g1) (Goal State -> Stream (State, x)
g2) = (State -> Stream (State, x)) -> Goal x
forall x. (State -> Stream (State, x)) -> Goal x
Goal (\State
state -> State -> Stream (State, x)
g1 State
state Stream (State, x) -> Stream (State, x) -> Stream (State, x)
forall a. Stream a -> Stream a -> Stream a
`interleave` State -> Stream (State, x)
g2 State
state)