module Haskus.Utils.ContFlow
( ContFlow (..)
, (>::>)
, (>:-:>)
, (>:%:>)
, fret
, fretN
, freturn
, freturnN
, frec
, ContListToTuple
, ContTupleToList
, StripR
, AddR
, fIf
, Then (..)
, Else (..)
)
where
import Haskus.Utils.Tuple
import Haskus.Utils.Types
import Haskus.Utils.Types.List
#define fdo ContFlow $ \__cs -> let ?__cs = __cs in do
newtype ContFlow (xs :: [*]) r = ContFlow (ContListToTuple xs r -> r)
type family ContListToTuple (xs :: [*]) r where
ContListToTuple xs r = ListToTuple (AddR xs r)
type family ContTupleToList t r :: [*] where
ContTupleToList t r = StripR (TupleToList t) r
type family AddR f r where
AddR '[] r = '[]
AddR (x ': xs) r = (x -> r) ': AddR xs r
type family StripR f r where
StripR '[] r = '[]
StripR ((x -> r) ': xs) r = x ': StripR xs r
StripR ((x -> w) ': xs) r =
TypeError ( 'Text "Invalid continuation return type `"
':<>: 'ShowType w ':<>: 'Text "', expecting `"
':<>: 'ShowType r ':<>: 'Text "'")
(>::>) :: ContFlow xs r -> ContListToTuple xs r -> r
(>::>) (ContFlow f) !cs = f cs
infixl 0 >::>
(>:-:>) :: ContFlow '[a] r -> (a -> r) -> r
(>:-:>) (ContFlow f) c = f (Single c)
infixl 0 >:-:>
(>:%:>) :: forall ts xs r.
( ReorderTuple ts (ContListToTuple xs r)
) => ContFlow xs r -> ts -> r
(>:%:>) (ContFlow f) !cs = f (tupleReorder cs)
infixl 0 >:%:>
fret :: forall x r t n xs.
( ExtractTuple n t (x -> r)
, xs ~ ContTupleToList t r
, Member x xs
, n ~ IndexOf x xs
, KnownNat n
, CheckNub xs
) => t -> (x -> r)
fret = tupleN @n @t @(x -> r)
freturn :: forall x r t n xs.
( ExtractTuple n t (x -> r)
, xs ~ ContTupleToList t r
, Member x xs
, n ~ IndexOf x xs
, KnownNat n
, CheckNub xs
, ?__cs :: t
) => x -> r
freturn = fret ?__cs
fretN :: forall n x r t xs.
( ExtractTuple n t (x -> r)
, xs ~ ContTupleToList t r
, x ~ Index n xs
, KnownNat n
) => t -> (x -> r)
fretN = tupleN @n @t @(x -> r)
freturnN :: forall n x r t xs.
( ExtractTuple n t (x -> r)
, xs ~ ContTupleToList t r
, x ~ Index n xs
, KnownNat n
, ?__cs :: t
) => x -> r
freturnN = fretN @n ?__cs
frec :: forall r xs.
( ?__cs :: ContListToTuple xs r
) => ContFlow xs r -> r
frec f = f >::> ?__cs
data Then = Then
data Else = Else
fIf :: Bool -> ContFlow '[Then,Else] r
fIf b = fdo
case b of
True -> freturn Then
False -> freturn Else