{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE ImpredicativeTypes #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE PartialTypeSignatures #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE QualifiedDo #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RoleAnnotations #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneKindSignatures #-}
{-# LANGUAGE TypeData #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UnboxedTuples #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE UnliftedNewtypes #-}
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# OPTIONS_GHC -Wno-name-shadowing #-}
{-# OPTIONS_GHC -Wno-partial-type-signatures #-}
{-# OPTIONS_GHC -Wno-redundant-constraints #-}
{-# OPTIONS_HADDOCK hide #-}

module Control.Monad.Borrow.Pure.BO.Internal (
  module Control.Monad.Borrow.Pure.BO.Internal,
) where

import Control.Exception qualified as SystemIO
import Control.Functor.Linear qualified as Control
import Control.Monad qualified as NonLinear
import Control.Monad.Borrow.Pure.Affine.Internal
import Control.Monad.Borrow.Pure.Lifetime
import Control.Monad.Borrow.Pure.Lifetime.Token
import Control.Monad.Borrow.Pure.Lifetime.Token.Internal
import Control.Monad.Borrow.Pure.Utils (coerceLin)
import Control.Monad.ST.Strict (ST)
import Control.Syntax.DataFlow qualified as DataFlow
import Data.Coerce qualified
import Data.Coerce.Directed.Unsafe
import Data.Functor.Identity (Identity)
import Data.Functor.Linear qualified as Data
import Data.Kind (Type)
import Data.Monoid qualified as Mon
import Data.Ord qualified as Ord
import Data.Semigroup qualified as Sem
import Data.Tuple (Solo (..))
import Data.Type.Equality ((:~:) (Refl))
import GHC.Base (TYPE)
import GHC.Base qualified as GHC
import GHC.Exts (State#, runRW#)
import GHC.ST qualified as ST
import GHC.TypeError (ErrorMessage (..))
import Generics.Linear
import Prelude.Linear
import Prelude.Linear qualified as PL
import Prelude.Linear.Unsatisfiable (Unsatisfiable, unsatisfiable)
import System.IO.Linear qualified as L
import Unsafe.Coerce (unsafeCoerce#)
import Unsafe.Linear qualified as Unsafe

-- NOTE: NOINLINE here is REALLY important, otherwise GHC will inline 'UnsafeLinearly' and common subexpression elimination
-- causes severe soundness bug that the same expression reuses the same
-- linear resource and sometimes SEGV.
askLinearly :: BO α Linearly
{-# NOINLINE askLinearly #-}
askLinearly :: forall (α :: Lifetime). BO α Linearly
askLinearly = BO α Linearly -> BO α Linearly
forall a. a -> a
GHC.noinline (BO α Linearly -> BO α Linearly) -> BO α Linearly -> BO α Linearly
forall a b (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b) %q -> a %p -> b
$ Linearly %1 -> BO α Linearly
forall a. a %1 -> BO α a
forall (f :: * -> *) a. Applicative f => a %1 -> f a
Control.pure Linearly
UnsafeLinearly

asksLinearlyM :: (Linearly %1 -> BO α r) %1 -> BO α r
{-# INLINE asksLinearlyM #-}
asksLinearlyM :: forall (α :: Lifetime) r. (Linearly %1 -> BO α r) %1 -> BO α r
asksLinearlyM Linearly %1 -> BO α r
k = Control.do
  lin <- BO α Linearly
forall (α :: Lifetime). BO α Linearly
askLinearly
  !a <- k lin
  Control.pure a

-- NOTE: We want to use @TypeData@ extension for 'ForBO', but it makes Haddock panic!

type ForBO :: Lifetime -> Type
data ForBO α

{- | Computation returning @a@ that can be performed only during the lifetime @α@.
     Internally it is a linear ST monad.
-}
newtype BO α a = BO (State# (ForBO α) %1 -> (# State# (ForBO α), a #))

instance (Semigroup w) => Semigroup (BO α w) where
  <> :: BO α w %1 -> BO α w %1 -> BO α w
(<>) = (w %1 -> w %1 -> w) %1 -> BO α w %1 -> BO α w %1 -> BO α w
forall a b c.
(a %1 -> b %1 -> c) %1 -> BO α a %1 -> BO α b %1 -> BO α c
forall (f :: * -> *) a b c.
Applicative f =>
(a %1 -> b %1 -> c) %1 -> f a %1 -> f b %1 -> f c
Control.liftA2 w %1 -> w %1 -> w
forall a. Semigroup a => a %1 -> a %1 -> a
(<>)
  {-# INLINE (<>) #-}

instance (Monoid w) => Monoid (BO α w) where
  mempty :: BO α w
mempty = w %1 -> BO α w
forall a. a %1 -> BO α a
forall (f :: * -> *) a. Applicative f => a %1 -> f a
Control.pure w
forall a. Monoid a => a
mempty
  {-# INLINE mempty #-}

unsafeUnBO :: BO α a %1 -> State# (ForBO α) %1 -> (# State# (ForBO α), a #)
{-# INLINE unsafeUnBO #-}
unsafeUnBO :: forall (α :: Lifetime) a.
BO α a %1 -> State# (ForBO α) %1 -> (# State# (ForBO α), a #)
unsafeUnBO (BO State# (ForBO α) %1 -> (# State# (ForBO α), a #)
f) = State# (ForBO α) %1 -> (# State# (ForBO α), a #)
f

assocRBO :: BO ((α /\ β) /\ γ) a %1 -> BO (α /\ (β /\ γ)) a
{-# INLINE assocRBO #-}
assocRBO :: forall (α :: Lifetime) (β :: Lifetime) (γ :: Lifetime) a.
BO ((α /\ β) /\ γ) a %1 -> BO (α /\ (β /\ γ)) a
assocRBO = BO ((α /\ β) /\ γ) a %1 -> BO (α /\ (β /\ γ)) a
forall (α :: Lifetime) a (β :: Lifetime). BO α a %1 -> BO β a
unsafeCastBO

assocLBO :: BO (α /\ (β /\ γ)) a %1 -> BO ((α /\ β) /\ γ) a
{-# INLINE assocLBO #-}
assocLBO :: forall (α :: Lifetime) (β :: Lifetime) (γ :: Lifetime) a.
BO (α /\ (β /\ γ)) a %1 -> BO ((α /\ β) /\ γ) a
assocLBO = BO (α /\ (β /\ γ)) a %1 -> BO ((α /\ β) /\ γ) a
forall (α :: Lifetime) a (β :: Lifetime). BO α a %1 -> BO β a
unsafeCastBO

assocBOEq :: forall α β γ a. BO ((α /\ β) /\ γ) a :~: BO (α /\ (β /\ γ)) a
{-# INLINE assocBOEq #-}
assocBOEq :: forall (α :: Lifetime) (β :: Lifetime) (γ :: Lifetime) a.
BO ((α /\ β) /\ γ) a :~: BO (α /\ (β /\ γ)) a
assocBOEq = (BO (α /\ (β /\ γ)) a :~: BO (α /\ (β /\ γ)) a)
%1 -> BO ((α /\ β) /\ γ) a :~: BO (α /\ (β /\ γ)) a
forall a b. a %1 -> b
Unsafe.coerce ((BO (α /\ (β /\ γ)) a :~: BO (α /\ (β /\ γ)) a)
 %1 -> BO ((α /\ β) /\ γ) a :~: BO (α /\ (β /\ γ)) a)
-> (BO (α /\ (β /\ γ)) a :~: BO (α /\ (β /\ γ)) a)
%1 -> BO ((α /\ β) /\ γ) a :~: BO (α /\ (β /\ γ)) a
forall a b (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b) %q -> a %p -> b
$ forall a. a :~: a
forall {k} (a :: k). a :~: a
Refl @(BO (α /\ β /\ γ) a)

instance Data.Functor (BO α) where
  fmap :: forall a b. (a %1 -> b) -> BO α a %1 -> BO α b
fmap a %1 -> b
f (BO State# (ForBO α) %1 -> (# State# (ForBO α), a #)
g) = (State# (ForBO α) %1 -> (# State# (ForBO α), b #)) -> BO α b
forall (α :: Lifetime) a.
(State# (ForBO α) %1 -> (# State# (ForBO α), a #)) -> BO α a
BO \State# (ForBO α)
s -> case State# (ForBO α) %1 -> (# State# (ForBO α), a #)
g State# (ForBO α)
s of
    (# State# (ForBO α)
s', a
a #) -> (# State# (ForBO α)
s', a %1 -> b
f a
a #)
  {-# INLINE fmap #-}

instance Control.Functor (BO α) where
  fmap :: forall a b. (a %1 -> b) %1 -> BO α a %1 -> BO α b
fmap a %1 -> b
f (BO State# (ForBO α) %1 -> (# State# (ForBO α), a #)
g) = (State# (ForBO α) %1 -> (# State# (ForBO α), b #)) -> BO α b
forall (α :: Lifetime) a.
(State# (ForBO α) %1 -> (# State# (ForBO α), a #)) -> BO α a
BO \State# (ForBO α)
s -> case State# (ForBO α) %1 -> (# State# (ForBO α), a #)
g State# (ForBO α)
s of
    (# State# (ForBO α)
s', a
a #) -> (# State# (ForBO α)
s', a %1 -> b
f a
a #)
  {-# INLINE fmap #-}

instance Data.Applicative (BO α) where
  pure :: forall a. a -> BO α a
pure a
a = a %1 -> BO α a
forall a. a %1 -> BO α a
forall (f :: * -> *) a. Applicative f => a %1 -> f a
Control.pure a
a
  {-# INLINE pure #-}

  <*> :: forall a b. BO α (a %1 -> b) %1 -> BO α a %1 -> BO α b
(<*>) = \BO α (a %1 -> b)
f BO α a
g -> BO α (a %1 -> b)
f BO α (a %1 -> b) %1 -> BO α a %1 -> BO α b
forall a b. BO α (a %1 -> b) %1 -> BO α a %1 -> BO α b
forall (f :: * -> *) a b.
Applicative f =>
f (a %1 -> b) %1 -> f a %1 -> f b
Control.<*> BO α a
g
  {-# INLINE (<*>) #-}

instance Control.Applicative (BO α) where
  pure :: forall a. a %1 -> BO α a
pure a
a = (State# (ForBO α) %1 -> (# State# (ForBO α), a #)) -> BO α a
forall (α :: Lifetime) a.
(State# (ForBO α) %1 -> (# State# (ForBO α), a #)) -> BO α a
BO \State# (ForBO α)
s -> (# State# (ForBO α)
s, a
a #)
  {-# INLINE pure #-}

  BO State# (ForBO α) %1 -> (# State# (ForBO α), a %1 -> b #)
f <*> :: forall a b. BO α (a %1 -> b) %1 -> BO α a %1 -> BO α b
<*> BO State# (ForBO α) %1 -> (# State# (ForBO α), a #)
g = (State# (ForBO α) %1 -> (# State# (ForBO α), b #)) -> BO α b
forall (α :: Lifetime) a.
(State# (ForBO α) %1 -> (# State# (ForBO α), a #)) -> BO α a
BO \State# (ForBO α)
s -> case State# (ForBO α) %1 -> (# State# (ForBO α), a %1 -> b #)
f State# (ForBO α)
s of
    (# State# (ForBO α)
s', a %1 -> b
h #) -> case State# (ForBO α) %1 -> (# State# (ForBO α), a #)
g State# (ForBO α)
s' of
      (# State# (ForBO α)
s'', a
a #) -> (# State# (ForBO α)
s'', a %1 -> b
h a
a #)
  {-# INLINE (<*>) #-}

instance Control.Monad (BO α) where
  BO State# (ForBO α) %1 -> (# State# (ForBO α), a #)
fa >>= :: forall a b. BO α a %1 -> (a %1 -> BO α b) %1 -> BO α b
>>= a %1 -> BO α b
f = (State# (ForBO α) %1 -> (# State# (ForBO α), b #)) -> BO α b
forall (α :: Lifetime) a.
(State# (ForBO α) %1 -> (# State# (ForBO α), a #)) -> BO α a
BO \State# (ForBO α)
s -> case State# (ForBO α) %1 -> (# State# (ForBO α), a #)
fa State# (ForBO α)
s of
    (# State# (ForBO α)
s', a
a #) -> (a %1 -> BO α b
f a
a) BO α b
%1 -> (BO α b %1 -> (# State# (ForBO α), b #))
%1 -> (# State# (ForBO α), b #)
forall a b (p :: Multiplicity) (q :: Multiplicity).
a %p -> (a %p -> b) %q -> b
PL.& \(BO State# (ForBO α) %1 -> (# State# (ForBO α), b #)
g) -> State# (ForBO α) %1 -> (# State# (ForBO α), b #)
g State# (ForBO α)
s'
  {-# INLINE (>>=) #-}

-- | Unsafely converts a 'BO' computation to linear 'L.IO'.
unsafeBOToLinIO :: BO α a %1 -> L.IO a
{-# INLINE unsafeBOToLinIO #-}
unsafeBOToLinIO :: forall (α :: Lifetime) a. BO α a %1 -> IO a
unsafeBOToLinIO (BO State# (ForBO α) %1 -> (# State# (ForBO α), a #)
f) = (State# RealWorld %1 -> (# State# RealWorld, a #)) -> IO a
forall a.
(State# RealWorld %1 -> (# State# RealWorld, a #)) -> IO a
L.IO ((State# (ForBO α) %1 -> (# State# (ForBO α), a #))
%1 -> State# RealWorld %1 -> (# State# RealWorld, a #)
forall a b. a %1 -> b
Unsafe.coerce State# (ForBO α) %1 -> (# State# (ForBO α), a #)
f)

{- |
Unsafely performs a linear 'L.IO' computation in 'BO' monad.

This is really, really unsafe. If you don't know what you are doing,
you MUST NOT use this function, otherwise you can break purity in a hard way.
-}
unsafeLinIOToBO :: L.IO a %1 -> BO α a
{-# INLINE unsafeLinIOToBO #-}
unsafeLinIOToBO :: forall a (α :: Lifetime). IO a %1 -> BO α a
unsafeLinIOToBO (L.IO State# RealWorld %1 -> (# State# RealWorld, a #)
f) = (State# (ForBO α) %1 -> (# State# (ForBO α), a #)) -> BO α a
forall (α :: Lifetime) a.
(State# (ForBO α) %1 -> (# State# (ForBO α), a #)) -> BO α a
BO ((State# RealWorld %1 -> (# State# RealWorld, a #))
%1 -> State# (ForBO α) %1 -> (# State# (ForBO α), a #)
forall a b. a %1 -> b
Unsafe.coerce State# RealWorld %1 -> (# State# RealWorld, a #)
f)

runBO# :: forall {rep} α (o :: TYPE rep). (State# (ForBO α) %1 -> o) %1 -> o
{-# INLINE runBO# #-}
runBO# :: forall (α :: Lifetime) o. (State# (ForBO α) %1 -> o) %1 -> o
runBO# = ((State# (ForBO α) %1 -> o) -> o)
%1 -> (State# (ForBO α) %1 -> o) %1 -> o
forall a b (p :: Multiplicity) (x :: Multiplicity).
(a %p -> b) %1 -> a %x -> b
Unsafe.toLinear \State# (ForBO α) %1 -> o
f -> (State# RealWorld -> o) -> o
forall o. (State# RealWorld -> o) -> o
runRW# \State# RealWorld
s ->
  State# (ForBO α) %1 -> o
f (State# RealWorld -> State# (ForBO α)
forall a b. a -> b
unsafeCoerce# State# RealWorld
s)

execBO :: BO α a %1 -> Now α %1 -> (Now α, a)
{-# INLINE execBO #-}
execBO :: forall (α :: Lifetime) a. BO α a %1 -> Now α %1 -> (Now α, a)
execBO (BO State# (ForBO α) %1 -> (# State# (ForBO α), a #)
f) !Now α
now =
  case (State# (ForBO α) %1 -> (# State# (ForBO α), a #))
%1 -> (# State# (ForBO α), a #)
forall (α :: Lifetime) o. (State# (ForBO α) %1 -> o) %1 -> o
runBO# State# (ForBO α) %1 -> (# State# (ForBO α), a #)
f of
    (# State# (ForBO α)
s, !a
a #) -> State# (ForBO α) %1 -> ()
forall a. State# a %1 -> ()
dropState# State# (ForBO α)
s () %1 -> (Now α, a) %1 -> (Now α, a)
forall a b. Consumable a => a %1 -> b %1 -> b
`PL.lseq` (Now α
now, a
a)

dropState# :: State# a %1 -> ()
{-# INLINE dropState# #-}
dropState# :: forall a. State# a %1 -> ()
dropState# = (State# a -> ()) %1 -> State# a %1 -> ()
forall a b (p :: Multiplicity) (x :: Multiplicity).
(a %p -> b) %1 -> a %x -> b
Unsafe.toLinear \ !State# a
_ -> ()

-- | See also 'Control.Monad.Borrow.Pure.scope'.
sexecBO :: BO (α /\ β) a %1 -> Now α %1 -> BO β (Now α, a)
{-# INLINE sexecBO #-}
sexecBO :: forall (α :: Lifetime) (β :: Lifetime) a.
BO (α /\ β) a %1 -> Now α %1 -> BO β (Now α, a)
sexecBO BO (α /\ β) a
f Now α
now = BO (α /\ β) (Now α, a) %1 -> BO β (Now α, a)
forall (α :: Lifetime) a (β :: Lifetime). BO α a %1 -> BO β a
unsafeCastBO ((Now α
now,) (a %1 -> (Now α, a)) %1 -> (a %1 -> a) -> a %1 -> (Now α, a)
forall b c a (q :: Multiplicity) (m :: Multiplicity)
       (n :: Multiplicity).
(b %1 -> c) %q -> (a %1 -> b) %m -> a %n -> c
PL.. (a -> a) %1 -> a %1 -> a
forall a b (p :: Multiplicity) (x :: Multiplicity).
(a %p -> b) %1 -> a %x -> b
Unsafe.toLinear (\ !a
a -> a
a) (a %1 -> (Now α, a))
%1 -> BO (α /\ β) a %1 -> BO (α /\ β) (Now α, a)
forall (f :: * -> *) a b.
Functor f =>
(a %1 -> b) %1 -> f a %1 -> f b
Control.<$> BO (α /\ β) a
f)

{- |
Coerces lifetime in 'BO' computation usafely and brutally.

This is really, really unsafe. If you don't know what you are doing,
you MUST NOT use this function, otherwise you will break the soundness of the type system.
-}
unsafeCastBO :: BO α a %1 -> BO β a
{-# INLINE unsafeCastBO #-}
unsafeCastBO :: forall (α :: Lifetime) a (β :: Lifetime). BO α a %1 -> BO β a
unsafeCastBO = BO α a %1 -> BO β a
forall a b. a %1 -> b
Unsafe.coerce

-- | Unsafely peforms a 'ST' computation in 'BO' monad.
unsafeSTToBO :: ST s a %1 -> BO α a
{-# INLINE unsafeSTToBO #-}
unsafeSTToBO :: forall s a (α :: Lifetime). ST s a %1 -> BO α a
unsafeSTToBO (ST.ST STRep s a
f) = (State# (ForBO α) %1 -> (# State# (ForBO α), a #)) -> BO α a
forall (α :: Lifetime) a.
(State# (ForBO α) %1 -> (# State# (ForBO α), a #)) -> BO α a
BO (STRep s a %1 -> State# (ForBO α) %1 -> (# State# (ForBO α), a #)
forall a b. a %1 -> b
Unsafe.coerce STRep s a
f)

{- |
Unsafely peforms a 'BO' computation in 'ST' monad.

This is really unsafe. If you don't know what you are doing, you MUST NOT use this function, otherwise you can break purity in a hard way.
-}
unsafeBOToST :: BO α a %1 -> ST s a
{-# INLINE unsafeBOToST #-}
unsafeBOToST :: forall (α :: Lifetime) a s. BO α a %1 -> ST s a
unsafeBOToST (BO State# (ForBO α) %1 -> (# State# (ForBO α), a #)
f) = STRep s a -> ST s a
forall s a. STRep s a -> ST s a
ST.ST ((State# (ForBO α) %1 -> (# State# (ForBO α), a #)) %1 -> STRep s a
forall a b. a %1 -> b
Unsafe.coerce State# (ForBO α) %1 -> (# State# (ForBO α), a #)
f)

{- |
Unsafely performs a standard, non-linear 'IO' computation in 'BO' monad.

This is really, really unsafe. If you don't know what you are doing,
you MUST NOT use this function, otherwise you can break purity in a hard way.
-}
unsafeSystemIOToBO :: IO a %1 -> BO α a
{-# INLINE unsafeSystemIOToBO #-}
unsafeSystemIOToBO :: forall a (α :: Lifetime). IO a %1 -> BO α a
unsafeSystemIOToBO (GHC.IO State# RealWorld -> (# State# RealWorld, a #)
a) = (State# (ForBO α) %1 -> (# State# (ForBO α), a #)) -> BO α a
forall (α :: Lifetime) a.
(State# (ForBO α) %1 -> (# State# (ForBO α), a #)) -> BO α a
BO ((State# RealWorld -> (# State# RealWorld, a #))
%1 -> State# (ForBO α) %1 -> (# State# (ForBO α), a #)
forall a b. a %1 -> b
Unsafe.coerce State# RealWorld -> (# State# RealWorld, a #)
a)

-- | Unsafely performs a 'BO' in the standard, non-linear 'IO' monad.
unsafeBOToSystemIO :: BO α a %1 -> IO a
{-# INLINE unsafeBOToSystemIO #-}
unsafeBOToSystemIO :: forall (α :: Lifetime) a. BO α a %1 -> IO a
unsafeBOToSystemIO (BO State# (ForBO α) %1 -> (# State# (ForBO α), a #)
f) = (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
GHC.IO ((State# (ForBO α) %1 -> (# State# (ForBO α), a #))
%1 -> State# RealWorld -> (# State# RealWorld, a #)
forall a b. a %1 -> b
Unsafe.coerce State# (ForBO α) %1 -> (# State# (ForBO α), a #)
f)

unsafePerformEvaluateUndupableBO :: BO α a %1 -> a
unsafePerformEvaluateUndupableBO :: forall (α :: Lifetime) a. BO α a %1 -> a
unsafePerformEvaluateUndupableBO (BO State# (ForBO α) %1 -> (# State# (ForBO α), a #)
f) = (State# (ForBO α) %1 -> a) %1 -> a
forall (α :: Lifetime) o. (State# (ForBO α) %1 -> o) %1 -> o
runBO# \State# (ForBO α)
s ->
  case (State# (ForBO α) -> State# (ForBO α))
%1 -> State# (ForBO α) %1 -> State# (ForBO α)
forall a b (p :: Multiplicity) (x :: Multiplicity).
(a %p -> b) %1 -> a %x -> b
Unsafe.toLinear State# (ForBO α) -> State# (ForBO α)
forall d. State# d -> State# d
GHC.noDuplicate# State# (ForBO α)
s of
    State# (ForBO α)
s -> case State# (ForBO α) %1 -> (# State# (ForBO α), a #)
f State# (ForBO α)
s of
      (# State# (ForBO α)
s, !a
a #) -> State# (ForBO α) %1 -> ()
forall a. State# a %1 -> ()
dropState# State# (ForBO α)
s () %1 -> a %1 -> a
forall a b. Consumable a => a %1 -> b %1 -> b
`PL.lseq` a
a

-- | Run two computations in parallel, returning their results as a tuple.
parBO :: BO α a %1 -> BO α b %1 -> BO α (a, b)
parBO :: forall (α :: Lifetime) a b. BO α a %1 -> BO α b %1 -> BO α (a, b)
parBO = (BO α a -> BO α b -> BO α (a, b))
%1 -> BO α a %1 -> BO α b %1 -> BO α (a, b)
forall a b c (p :: Multiplicity) (q :: Multiplicity)
       (x :: Multiplicity) (y :: Multiplicity).
(a %p -> b %q -> c) %1 -> a %x -> b %y -> c
Unsafe.toLinear2 \BO α a
a BO α b
b ->
  (State# (ForBO α) %1 -> (# State# (ForBO α), (a, b) #))
-> BO α (a, b)
forall (α :: Lifetime) a.
(State# (ForBO α) %1 -> (# State# (ForBO α), a #)) -> BO α a
BO ((State# (ForBO α) %1 -> (# State# (ForBO α), (a, b) #))
 -> BO α (a, b))
-> (State# (ForBO α) %1 -> (# State# (ForBO α), (a, b) #))
-> BO α (a, b)
forall a b (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b) %q -> a %p -> b
$
    (State# (ForBO α) -> (# State# (ForBO α), (a, b) #))
%1 -> State# (ForBO α) %1 -> (# State# (ForBO α), (a, b) #)
forall a b (p :: Multiplicity) (x :: Multiplicity).
(a %p -> b) %1 -> a %x -> b
Unsafe.toLinear \State# (ForBO α)
s ->
      case (a -> State# (ForBO α) -> (# State# (ForBO α), a #))
%1 -> a -> State# (ForBO α) -> (# State# (ForBO α), a #)
forall a b c (p :: Multiplicity) (q :: Multiplicity)
       (x :: Multiplicity) (y :: Multiplicity).
(a %p -> b %q -> c) %1 -> a %x -> b %y -> c
Unsafe.toLinear2 a -> State# (ForBO α) -> (# State# (ForBO α), a #)
forall a d. a -> State# d -> (# State# d, a #)
GHC.spark# (case BO α a %1 -> State# (ForBO α) %1 -> (# State# (ForBO α), a #)
forall (α :: Lifetime) a.
BO α a %1 -> State# (ForBO α) %1 -> (# State# (ForBO α), a #)
unsafeUnBO BO α a
a (State# (ForBO α) -> State# (ForBO α)
forall d. State# d -> State# d
GHC.noDuplicate# State# (ForBO α)
s) of (# State# (ForBO α)
_, a
a #) -> a -> a
forall a. a -> a
GHC.lazy a
a) State# (ForBO α)
s of
        (# State# (ForBO α)
_, a
a #) ->
          case (b -> State# (ForBO α) -> (# State# (ForBO α), b #))
%1 -> b -> State# (ForBO α) -> (# State# (ForBO α), b #)
forall a b c (p :: Multiplicity) (q :: Multiplicity)
       (x :: Multiplicity) (y :: Multiplicity).
(a %p -> b %q -> c) %1 -> a %x -> b %y -> c
Unsafe.toLinear2 b -> State# (ForBO α) -> (# State# (ForBO α), b #)
forall a d. a -> State# d -> (# State# d, a #)
GHC.spark# (case BO α b %1 -> State# (ForBO α) %1 -> (# State# (ForBO α), b #)
forall (α :: Lifetime) a.
BO α a %1 -> State# (ForBO α) %1 -> (# State# (ForBO α), a #)
unsafeUnBO BO α b
b (State# (ForBO α) -> State# (ForBO α)
forall d. State# d -> State# d
GHC.noDuplicate# State# (ForBO α)
s) of (# State# (ForBO α)
_, b
b #) -> b -> b
forall a. a -> a
GHC.lazy b
b) State# (ForBO α)
s of
            (# State# (ForBO α)
_, b
b #) ->
              case (a -> State# (ForBO α) -> (# State# (ForBO α), a #))
%1 -> a -> State# (ForBO α) -> (# State# (ForBO α), a #)
forall a b c (p :: Multiplicity) (q :: Multiplicity)
       (x :: Multiplicity) (y :: Multiplicity).
(a %p -> b %q -> c) %1 -> a %x -> b %y -> c
Unsafe.toLinear2 a -> State# (ForBO α) -> (# State# (ForBO α), a #)
forall a d. a -> State# d -> (# State# d, a #)
GHC.seq# a
a State# (ForBO α)
s of
                (# State# (ForBO α)
s, !a
a #) -> case (b -> State# (ForBO α) -> (# State# (ForBO α), b #))
%1 -> b -> State# (ForBO α) -> (# State# (ForBO α), b #)
forall a b c (p :: Multiplicity) (q :: Multiplicity)
       (x :: Multiplicity) (y :: Multiplicity).
(a %p -> b %q -> c) %1 -> a %x -> b %y -> c
Unsafe.toLinear2 b -> State# (ForBO α) -> (# State# (ForBO α), b #)
forall a d. a -> State# d -> (# State# d, a #)
GHC.seq# b
b State# (ForBO α)
s of
                  (# State# (ForBO α)
s, !b
b #) -> (# State# (ForBO α)
s, (a
a, b
b) #)

evaluateBO :: a %1 -> BO α a
{-# INLINE evaluateBO #-}
evaluateBO :: forall a (α :: Lifetime). a %1 -> BO α a
evaluateBO a
a = IO a %1 -> BO α a
forall a (α :: Lifetime). IO a %1 -> BO α a
unsafeSystemIOToBO ((a -> IO a) %1 -> a %1 -> IO a
forall a b (p :: Multiplicity) (x :: Multiplicity).
(a %p -> b) %1 -> a %x -> b
Unsafe.toLinear a -> IO a
forall a. a -> IO a
SystemIO.evaluate a
a)

-- | Alias of kind 'ak' to a resource of type 'a'.
type Alias :: AliasKind -> Lifetime -> Type -> Type
newtype Alias ak α a = UnsafeAlias a

unsafeUnalias :: Alias ak α a %1 -> a
unsafeUnalias :: forall (ak :: AliasKind) (α :: Lifetime) a. Alias ak α a %1 -> a
unsafeUnalias (UnsafeAlias a
x) = a
x

type role Alias nominal nominal representational

-- | Alias kind.
data AliasKind
  = -- | Borrower.
    Borrow BorrowKind
  | -- | Lender.
    Lend

-- | Borrower kind.
data BorrowKind
  = -- | Mutable.
    Mut
  | -- | Shared.
    Share

-- | Borrower of kind @bk@ that is active during the lifetime @α@.
type Borrow :: BorrowKind -> Lifetime -> Type -> Type
type Borrow bk = Alias ('Borrow bk)

-- | Mutable borrower, which is affine and can update the data.
type Mut :: Lifetime -> Type -> Type
type Mut = Borrow 'Mut

assocBorrowR ::
  Borrow bk ((α /\ β) /\ γ) a %1 ->
  Borrow bk (α /\ (β /\ γ)) a
{-# INLINE assocBorrowR #-}
assocBorrowR :: forall (bk :: BorrowKind) (α :: Lifetime) (β :: Lifetime)
       (γ :: Lifetime) a.
Borrow bk ((α /\ β) /\ γ) a %1 -> Borrow bk (α /\ (β /\ γ)) a
assocBorrowR = Borrow bk ((α /\ β) /\ γ) a %1 -> Borrow bk (α /\ (β /\ γ)) a
forall a b. Coercible a b => a %1 -> b
coerceLin

assocBorrowL ::
  Borrow bk (α /\ (β /\ γ)) a %1 ->
  Borrow bk ((α /\ β) /\ γ) a
{-# INLINE assocBorrowL #-}
assocBorrowL :: forall (bk :: BorrowKind) (α :: Lifetime) (β :: Lifetime)
       (γ :: Lifetime) a.
Borrow bk (α /\ (β /\ γ)) a %1 -> Borrow bk ((α /\ β) /\ γ) a
assocBorrowL = Borrow bk (α /\ (β /\ γ)) a %1 -> Borrow bk ((α /\ β) /\ γ) a
forall a b. Coercible a b => a %1 -> b
coerceLin

assocBorrowEq ::
  forall bk α β γ a.
  (Borrow bk ((α /\ β) /\ γ) a) :~: (Borrow bk (α /\ (β /\ γ)) a)
{-# INLINE assocBorrowEq #-}
assocBorrowEq :: forall (bk :: BorrowKind) (α :: Lifetime) (β :: Lifetime)
       (γ :: Lifetime) a.
Borrow bk ((α /\ β) /\ γ) a :~: Borrow bk (α /\ (β /\ γ)) a
assocBorrowEq = (Borrow bk (α /\ (β /\ γ)) a :~: Borrow bk (α /\ (β /\ γ)) a)
%1 -> Borrow bk ((α /\ β) /\ γ) a :~: Borrow bk (α /\ (β /\ γ)) a
forall a b. a %1 -> b
Unsafe.coerce ((Borrow bk (α /\ (β /\ γ)) a :~: Borrow bk (α /\ (β /\ γ)) a)
 %1 -> Borrow bk ((α /\ β) /\ γ) a :~: Borrow bk (α /\ (β /\ γ)) a)
-> (Borrow bk (α /\ (β /\ γ)) a :~: Borrow bk (α /\ (β /\ γ)) a)
%1 -> Borrow bk ((α /\ β) /\ γ) a :~: Borrow bk (α /\ (β /\ γ)) a
forall a b (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b) %q -> a %p -> b
$ forall a. a :~: a
forall {k} (a :: k). a :~: a
Refl @(Borrow bk (α /\ β /\ γ) a)

assocLendR ::
  Lend ((α /\ β) /\ γ) a %1 ->
  Lend (α /\ (β /\ γ)) a
{-# INLINE assocLendR #-}
assocLendR :: forall (α :: Lifetime) (β :: Lifetime) (γ :: Lifetime) a.
Lend ((α /\ β) /\ γ) a %1 -> Lend (α /\ (β /\ γ)) a
assocLendR = Lend ((α /\ β) /\ γ) a %1 -> Lend (α /\ (β /\ γ)) a
forall a b. Coercible a b => a %1 -> b
coerceLin

assocLendL ::
  Lend (α /\ (β /\ γ)) a %1 ->
  Lend ((α /\ β) /\ γ) a
{-# INLINE assocLendL #-}
assocLendL :: forall (α :: Lifetime) (β :: Lifetime) (γ :: Lifetime) a.
Lend (α /\ (β /\ γ)) a %1 -> Lend ((α /\ β) /\ γ) a
assocLendL = Lend (α /\ (β /\ γ)) a %1 -> Lend ((α /\ β) /\ γ) a
forall a b. Coercible a b => a %1 -> b
coerceLin

assocLendEq :: forall α β γ a. (Lend ((α /\ β) /\ γ) a) :~: (Lend (α /\ (β /\ γ)) a)
{-# INLINE assocLendEq #-}
assocLendEq :: forall (α :: Lifetime) (β :: Lifetime) (γ :: Lifetime) a.
Lend ((α /\ β) /\ γ) a :~: Lend (α /\ (β /\ γ)) a
assocLendEq = (Lend (α /\ (β /\ γ)) a :~: Lend (α /\ (β /\ γ)) a)
%1 -> Lend ((α /\ β) /\ γ) a :~: Lend (α /\ (β /\ γ)) a
forall a b. a %1 -> b
Unsafe.coerce ((Lend (α /\ (β /\ γ)) a :~: Lend (α /\ (β /\ γ)) a)
 %1 -> Lend ((α /\ β) /\ γ) a :~: Lend (α /\ (β /\ γ)) a)
-> (Lend (α /\ (β /\ γ)) a :~: Lend (α /\ (β /\ γ)) a)
%1 -> Lend ((α /\ β) /\ γ) a :~: Lend (α /\ (β /\ γ)) a
forall a b (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b) %q -> a %p -> b
$ forall a. a :~: a
forall {k} (a :: k). a :~: a
Refl @(Lend (α /\ β /\ γ) a)

instance (bk ~ 'Mut) => LinearOnly (Borrow bk α a) where
  linearOnly :: LinearOnlyWitness (Borrow bk α a)
linearOnly = LinearOnlyWitness (Borrow bk α a)
forall {k} (a :: k). LinearOnlyWitness a
UnsafeLinearOnly

deriving via AsAffine (Borrow bk α a) instance Consumable (Borrow bk α a)

-- | Shared borrower, which is unrestricted but usually can only read from the data.
type Share :: Lifetime -> Type -> Type
type Share = Borrow 'Share

instance Affine (Borrow bk α a) where
  aff :: Borrow bk α a %1 -> Aff (Borrow bk α a)
aff = Borrow bk α a -> Aff (Borrow bk α a)
forall a. a -> Aff a
UnsafeAff
  {-# INLINE aff #-}

instance (k ~ 'Borrow 'Share) => Dupable (Alias k α a) where
  dup2 :: Alias k α a %1 -> (Alias k α a, Alias k α a)
dup2 = (Alias k α a -> (Alias k α a, Alias k α a))
%1 -> Alias k α a %1 -> (Alias k α a, Alias k α a)
forall a b (p :: Multiplicity) (x :: Multiplicity).
(a %p -> b) %1 -> a %x -> b
Unsafe.toLinear ((Alias k α a -> (Alias k α a, Alias k α a))
 %1 -> Alias k α a %1 -> (Alias k α a, Alias k α a))
-> (Alias k α a -> (Alias k α a, Alias k α a))
%1 -> Alias k α a
%1 -> (Alias k α a, Alias k α a)
forall a b (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b) %q -> a %p -> b
$ (Alias k α a -> Alias k α a -> (Alias k α a, Alias k α a))
-> Alias k α a -> (Alias k α a, Alias k α a)
forall (m :: * -> *) a. Monad m => m (m a) -> m a
NonLinear.join (,)
  {-# INLINE dup2 #-}

instance (k ~ 'Borrow 'Share) => Movable (Alias k α a) where
  move :: Alias k α a %1 -> Ur (Alias k α a)
move = (Alias k α a -> Ur (Alias k α a))
%1 -> Alias k α a %1 -> Ur (Alias k α a)
forall a b (p :: Multiplicity) (x :: Multiplicity).
(a %p -> b) %1 -> a %x -> b
Unsafe.toLinear Alias k α a -> Ur (Alias k α a)
forall a. a -> Ur a
Ur
  {-# INLINE move #-}

instance (α >= β, a <: b) => BO α a <: BO β b where
  subtype :: SubtypeWitness (BO α a) (BO β b)
subtype = SubtypeWitness (BO α a) (BO β b)
forall {k} {k1} (a :: k) (b :: k1). SubtypeWitness a b
UnsafeSubtype

instance (α >= β, a <: b, b <: a) => Mut α a <: Mut β b where
  subtype :: SubtypeWitness (Mut α a) (Mut β b)
subtype = SubtypeWitness (Mut α a) (Mut β b)
forall {k} {k1} (a :: k) (b :: k1). SubtypeWitness a b
UnsafeSubtype

instance (α >= β, a <: b) => Share α a <: Share β b where
  subtype :: SubtypeWitness (Share α a) (Share β b)
subtype = SubtypeWitness (Share α a) (Share β b)
forall {k} {k1} (a :: k) (b :: k1). SubtypeWitness a b
UnsafeSubtype

-- | Lender, which can retrieve the lifetime at the lifetime @α@.
type Lend :: Lifetime -> Type -> Type
type Lend = Alias 'Lend

instance (α <= β, a <: b) => Lend α a <: Lend β b where
  subtype :: SubtypeWitness (Lend α a) (Lend β b)
subtype = SubtypeWitness (Lend α a) (Lend β b)
forall {k} {k1} (a :: k) (b :: k1). SubtypeWitness a b
UnsafeSubtype

{- |
Borrow a resource linearly and obtain the mutable borrow to it and 'Lend' witness to 'reclaim the resource to lend at the 'End' of the lifetime.

For typical usage, you should use 'Control.Monad.Borrow.Pure.borrowM' to avoid type ambiguity.
-}
borrow :: forall α a. a %1 -> Linearly %1 -> (Mut α a, Lend α a)
borrow :: forall (α :: Lifetime) a.
a %1 -> Linearly %1 -> (Mut α a, Lend α a)
borrow = (a -> Linearly -> (Mut α a, Lend α a))
%1 -> a %1 -> Linearly %1 -> (Mut α a, Lend α a)
forall a b c (p :: Multiplicity) (q :: Multiplicity)
       (x :: Multiplicity) (y :: Multiplicity).
(a %p -> b %q -> c) %1 -> a %x -> b %y -> c
Unsafe.toLinear2 \ !a
a !Linearly
_ ->
  (a -> Mut α a
forall (ak :: AliasKind) (α :: Lifetime) a. a -> Alias ak α a
UnsafeAlias a
a, a -> Lend α a
forall (ak :: AliasKind) (α :: Lifetime) a. a -> Alias ak α a
UnsafeAlias a
a)

-- | Shares a mutable borrow, invalidating the original one.
share :: Borrow k α a %1 -> Ur (Share α a)
share :: forall (k :: BorrowKind) (α :: Lifetime) a.
Borrow k α a %1 -> Ur (Share α a)
share = (Borrow k α a -> Ur (Share α a))
%1 -> Borrow k α a %1 -> Ur (Share α a)
forall a b (p :: Multiplicity) (x :: Multiplicity).
(a %p -> b) %1 -> a %x -> b
Unsafe.toLinear \(UnsafeAlias !a
a) -> Share α a -> Ur (Share α a)
forall a. a -> Ur a
Ur (a -> Share α a
forall (ak :: AliasKind) (α :: Lifetime) a. a -> Alias ak α a
UnsafeAlias a
a)

-- | Reclaims a 'borrow'ed resource at the 'End' of lifetime @α'.
reclaim' :: Lend α a %1 -> After α a
reclaim' :: forall (α :: Lifetime) a. Lend α a %1 -> After α a
reclaim' Lend α a
l = (End α => a) -> After α a
forall (α :: Lifetime) a. (End α => a) -> After α a
After (Lend α a %1 -> a
forall (α :: Lifetime) a. End α => Lend α a %1 -> a
reclaim Lend α a
l)

-- | Reclaims a 'borrow'ed resource at the 'End' of lifetime @α'.
reclaim :: (End α) => Lend α a %1 -> a
reclaim :: forall (α :: Lifetime) a. End α => Lend α a %1 -> a
reclaim = \(UnsafeAlias !a
a) -> a
a

-- | Reborrow a mutable borrow into a sublifetime.
reborrow :: forall β α a. (α >= β) => Mut α a %1 -> (Mut β a, Lend β (Mut α a))
reborrow :: forall (β :: Lifetime) (α :: Lifetime) a.
(α >= β) =>
Mut α a %1 -> (Mut β a, Lend β (Mut α a))
reborrow = (Mut α a -> (Mut β a, Lend β (Mut α a)))
%1 -> Mut α a %1 -> (Mut β a, Lend β (Mut α a))
forall a b (p :: Multiplicity) (x :: Multiplicity).
(a %p -> b) %1 -> a %x -> b
Unsafe.toLinear \ !Mut α a
mutA ->
  (Mut α a -> Mut β a
forall a b. Coercible a b => a -> b
Data.Coerce.coerce Mut α a
mutA, Mut α a -> Lend β (Mut α a)
forall a b. Coercible a b => a -> b
Data.Coerce.coerce Mut α a
mutA)

-- | Collapse a borrower to a mutable borrower.
joinMut :: Borrow bk α (Mut β a) %1 -> Borrow bk (α /\ β) a
joinMut :: forall (bk :: BorrowKind) (α :: Lifetime) (β :: Lifetime) a.
Borrow bk α (Mut β a) %1 -> Borrow bk (α /\ β) a
joinMut = Borrow bk α (Mut β a) %1 -> Borrow bk (α /\ β) a
forall a b. Coercible a b => a %1 -> b
coerceLin

joinLend :: Lend α (Lend α a) %1 -> Lend α a
joinLend :: forall (α :: Lifetime) a. Lend α (Lend α a) %1 -> Lend α a
joinLend = Lend α (Lend α a) %1 -> Lend α a
forall a b. Coercible a b => a %1 -> b
coerceLin

-- | Distribute an alias over a functor.
class DistributesAlias f where
  split_ :: Alias ak α (f x) %1 -> f (Alias ak α x)
  default split_ ::
    (GenericDistributesAlias f) =>
    Alias ak α (f x) %1 -> f (Alias ak α x)
  split_ = Alias ak α (f x) %1 -> f (Alias ak α x)
forall (f :: * -> *) x (ak :: AliasKind) (α :: Lifetime).
GenericDistributesAlias f =>
Alias ak α (f x) %1 -> f (Alias ak α x)
genericSplit

split ::
  forall f x ak α.
  (DistributesAlias f) =>
  Alias ak α (f x) %1 -> f (Alias ak α x)
{-# INLINE [1] split #-}
split :: forall (f :: * -> *) x (ak :: AliasKind) (α :: Lifetime).
DistributesAlias f =>
Alias ak α (f x) %1 -> f (Alias ak α x)
split = Alias ak α (f x) %1 -> f (Alias ak α x)
forall (ak :: AliasKind) (α :: Lifetime) x.
Alias ak α (f x) %1 -> f (Alias ak α x)
forall (f :: * -> *) (ak :: AliasKind) (α :: Lifetime) x.
DistributesAlias f =>
Alias ak α (f x) %1 -> f (Alias ak α x)
split_

deriving anyclass instance DistributesAlias Identity

deriving anyclass instance DistributesAlias []

deriving anyclass instance DistributesAlias Maybe

deriving anyclass instance DistributesAlias Solo

deriving anyclass instance DistributesAlias Ord.Down

deriving anyclass instance DistributesAlias Sem.Dual

deriving anyclass instance DistributesAlias Sem.Max

deriving anyclass instance DistributesAlias Sem.Min

deriving anyclass instance DistributesAlias Sem.First

deriving anyclass instance DistributesAlias Sem.Last

deriving anyclass instance DistributesAlias Mon.First

deriving anyclass instance DistributesAlias Mon.Last

splitPair :: Alias ak α (a, b) %1 -> (Alias ak α a, Alias ak α b)
{-# INLINE splitPair #-}
splitPair :: forall (ak :: AliasKind) (α :: Lifetime) a b.
Alias ak α (a, b) %1 -> (Alias ak α a, Alias ak α b)
splitPair = Alias ak α (a, b) %1 -> (Alias ak α a, Alias ak α b)
forall a b. Coercible a b => a %1 -> b
coerceLin

splitEither :: Alias ak α (Either a b) %1 -> Either (Alias ak α a) (Alias ak α b)
{-# INLINE splitEither #-}
splitEither :: forall (ak :: AliasKind) (α :: Lifetime) a b.
Alias ak α (Either a b) %1 -> Either (Alias ak α a) (Alias ak α b)
splitEither = Alias ak α (Either a b) %1 -> Either (Alias ak α a) (Alias ak α b)
forall a b. Coercible a b => a %1 -> b
coerceLin

instance (Unsatisfiable ('Text "Use splitEither directly!")) => DistributesAlias (Either e) where
  {-# INLINE split_ #-}
  split_ :: forall (ak :: AliasKind) (α :: Lifetime) x.
Alias ak α (Either e x) %1 -> Either e (Alias ak α x)
split_ = Alias ak α (Either e x) %1 -> Either e (Alias ak α x)
forall a. Bottom => a
unsatisfiable

instance (Unsatisfiable ('Text "Use splitPair instead!")) => DistributesAlias ((,) a) where
  {-# INLINE split_ #-}
  split_ :: forall (ak :: AliasKind) (α :: Lifetime) x.
Alias ak α (a, x) %1 -> (a, Alias ak α x)
split_ = Alias ak α (a, x) %1 -> (a, Alias ak α x)
forall a. Bottom => a
unsatisfiable

type GenericDistributesAlias f = (Generic1 f, GDistributeAlias (Rep1 f))

genericSplit ::
  forall f x ak α.
  (GenericDistributesAlias f) =>
  Alias ak α (f x) %1 -> f (Alias ak α x)
{-# INLINE genericSplit #-}
genericSplit :: forall (f :: * -> *) x (ak :: AliasKind) (α :: Lifetime).
GenericDistributesAlias f =>
Alias ak α (f x) %1 -> f (Alias ak α x)
genericSplit =
  Rep1 f (Alias ak α x) %1 -> f (Alias ak α x)
forall p (m :: Multiplicity). Rep1 f p %m -> f p
forall {k} (f :: k -> *) (p :: k) (m :: Multiplicity).
Generic1 f =>
Rep1 f p %m -> f p
to1
    (Rep1 f (Alias ak α x) %1 -> f (Alias ak α x))
-> (Alias ak α (f x) %1 -> Rep1 f (Alias ak α x))
-> Alias ak α (f x)
%1 -> f (Alias ak α x)
forall b c a (q :: Multiplicity) (m :: Multiplicity)
       (n :: Multiplicity).
(b %1 -> c) %q -> (a %1 -> b) %m -> a %n -> c
. forall (f :: * -> *) (ak :: AliasKind) (α :: Lifetime) x.
GDistributeAlias f =>
Alias ak α (f x) %1 -> f (Alias ak α x)
gdistributeAlias @(Rep1 f)
    (Alias ak α (Rep1 f x) %1 -> Rep1 f (Alias ak α x))
-> (Alias ak α (f x) %1 -> Alias ak α (Rep1 f x))
-> Alias ak α (f x)
%1 -> Rep1 f (Alias ak α x)
forall b c a (q :: Multiplicity) (m :: Multiplicity)
       (n :: Multiplicity).
(b %1 -> c) %q -> (a %1 -> b) %m -> a %n -> c
. (f x %1 -> Rep1 f x)
%1 -> Alias ak α (f x) %1 -> Alias ak α (Rep1 f x)
forall a b (ak :: AliasKind) (α :: Lifetime).
(a %1 -> b) %1 -> Alias ak α a %1 -> Alias ak α b
unsafeMapAlias f x %1 -> Rep1 f x
forall p (m :: Multiplicity). f p %m -> Rep1 f p
forall {k} (f :: k -> *) (p :: k) (m :: Multiplicity).
Generic1 f =>
f p %m -> Rep1 f p
from1

unsafeMapAlias :: (a %1 -> b) %1 -> Alias ak α a %1 -> Alias ak α b
{-# INLINE unsafeMapAlias #-}
unsafeMapAlias :: forall a b (ak :: AliasKind) (α :: Lifetime).
(a %1 -> b) %1 -> Alias ak α a %1 -> Alias ak α b
unsafeMapAlias a %1 -> b
f = (a %1 -> b) %1 -> Alias ak α a %1 -> Alias ak α b
forall a b. Coercible a b => a %1 -> b
coerceLin (\a
x -> let !y :: b
y = a %1 -> b
f a
x in b
y)

instance (GenericDistributesAlias f) => DistributesAlias (Generically1 f) where
  {-# INLINE split_ #-}
  split_ :: forall (ak :: AliasKind) (α :: Lifetime) x.
Alias ak α (Generically1 f x) %1 -> Generically1 f (Alias ak α x)
split_ = f (Alias ak α x) -> Generically1 f (Alias ak α x)
forall {k} (f :: k -> *) (a :: k). f a -> Generically1 f a
Generically1 (f (Alias ak α x) %1 -> Generically1 f (Alias ak α x))
-> (Alias ak α (Generically1 f x) %1 -> f (Alias ak α x))
-> Alias ak α (Generically1 f x)
%1 -> Generically1 f (Alias ak α x)
forall b c a (q :: Multiplicity) (m :: Multiplicity)
       (n :: Multiplicity).
(b %1 -> c) %q -> (a %1 -> b) %m -> a %n -> c
. Alias ak α (f x) %1 -> f (Alias ak α x)
forall (f :: * -> *) x (ak :: AliasKind) (α :: Lifetime).
GenericDistributesAlias f =>
Alias ak α (f x) %1 -> f (Alias ak α x)
genericSplit (Alias ak α (f x) %1 -> f (Alias ak α x))
-> (Alias ak α (Generically1 f x) %1 -> Alias ak α (f x))
-> Alias ak α (Generically1 f x)
%1 -> f (Alias ak α x)
forall b c a (q :: Multiplicity) (m :: Multiplicity)
       (n :: Multiplicity).
(b %1 -> c) %q -> (a %1 -> b) %m -> a %n -> c
. (Generically1 f x %1 -> f x)
%1 -> Alias ak α (Generically1 f x) %1 -> Alias ak α (f x)
forall a b (ak :: AliasKind) (α :: Lifetime).
(a %1 -> b) %1 -> Alias ak α a %1 -> Alias ak α b
unsafeMapAlias \(Generically1 f x
f) -> f x
f

class GDistributeAlias f where
  gdistributeAlias :: Alias ak α (f x) %1 -> f (Alias ak α x)

instance
  ( GDistributeAlias f
  , GDistributeAlias g
  ) =>
  GDistributeAlias (f :*: g)
  where
  {-# INLINE gdistributeAlias #-}
  gdistributeAlias :: forall (ak :: AliasKind) (α :: Lifetime) x.
Alias ak α ((:*:) f g x) %1 -> (:*:) f g (Alias ak α x)
gdistributeAlias !(UnsafeAlias !(f x
f :*: g x
g)) =
    DataFlow.do
      !f <- Alias ak α (f x) %1 -> f (Alias ak α x)
forall (ak :: AliasKind) (α :: Lifetime) x.
Alias ak α (f x) %1 -> f (Alias ak α x)
forall (f :: * -> *) (ak :: AliasKind) (α :: Lifetime) x.
GDistributeAlias f =>
Alias ak α (f x) %1 -> f (Alias ak α x)
gdistributeAlias (Alias ak α (f x) %1 -> f (Alias ak α x))
-> Alias ak α (f x) %1 -> f (Alias ak α x)
forall a b (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b) %q -> a %p -> b
$ f x -> Alias ak α (f x)
forall (ak :: AliasKind) (α :: Lifetime) a. a -> Alias ak α a
UnsafeAlias f x
f
      !g <- gdistributeAlias $ UnsafeAlias g
      f :*: g

instance
  ( GDistributeAlias f
  , GDistributeAlias g
  ) =>
  GDistributeAlias (f :+: g)
  where
  {-# INLINE gdistributeAlias #-}
  gdistributeAlias :: forall (ak :: AliasKind) (α :: Lifetime) x.
Alias ak α ((:+:) f g x) %1 -> (:+:) f g (Alias ak α x)
gdistributeAlias (UnsafeAlias (:+:) f g x
x) = case (:+:) f g x
x of
    L1 !f x
l -> f (Alias ak α x) -> (:+:) f g (Alias ak α x)
forall k (f :: k -> *) (g :: k -> *) (p :: k). f p -> (:+:) f g p
L1 (Alias ak α (f x) %1 -> f (Alias ak α x)
forall (ak :: AliasKind) (α :: Lifetime) x.
Alias ak α (f x) %1 -> f (Alias ak α x)
forall (f :: * -> *) (ak :: AliasKind) (α :: Lifetime) x.
GDistributeAlias f =>
Alias ak α (f x) %1 -> f (Alias ak α x)
gdistributeAlias (f x -> Alias ak α (f x)
forall (ak :: AliasKind) (α :: Lifetime) a. a -> Alias ak α a
UnsafeAlias f x
l))
    R1 !g x
r -> g (Alias ak α x) -> (:+:) f g (Alias ak α x)
forall k (f :: k -> *) (g :: k -> *) (p :: k). g p -> (:+:) f g p
R1 (Alias ak α (g x) %1 -> g (Alias ak α x)
forall (ak :: AliasKind) (α :: Lifetime) x.
Alias ak α (g x) %1 -> g (Alias ak α x)
forall (f :: * -> *) (ak :: AliasKind) (α :: Lifetime) x.
GDistributeAlias f =>
Alias ak α (f x) %1 -> f (Alias ak α x)
gdistributeAlias (g x -> Alias ak α (g x)
forall (ak :: AliasKind) (α :: Lifetime) a. a -> Alias ak α a
UnsafeAlias g x
r))

instance
  (Unsatisfiable (Text "Nonlinear fields cannot distribute borrows!")) =>
  GDistributeAlias (MP1 GHC.Many f)
  where
  {-# INLINE gdistributeAlias #-}
  gdistributeAlias :: forall (ak :: AliasKind) (α :: Lifetime) x.
Alias ak α (MP1 'Many f x) %1 -> MP1 'Many f (Alias ak α x)
gdistributeAlias = Alias ak α (MP1 'Many f x) %1 -> MP1 'Many f (Alias ak α x)
forall a. Bottom => a
unsatisfiable

instance (GDistributeAlias f) => GDistributeAlias (MP1 GHC.One f) where
  {-# INLINE gdistributeAlias #-}
  gdistributeAlias :: forall (ak :: AliasKind) (α :: Lifetime) x.
Alias ak α (MP1 'One f x) %1 -> MP1 'One f (Alias ak α x)
gdistributeAlias =
    f (Alias ak α x) %1 -> MP1 'One f (Alias ak α x)
forall {k} (b :: k -> *) (c :: k) (a :: Multiplicity).
b c %a -> MP1 a b c
MP1 (f (Alias ak α x) %1 -> MP1 'One f (Alias ak α x))
-> (Alias ak α (MP1 'One f x) %1 -> f (Alias ak α x))
-> Alias ak α (MP1 'One f x)
%1 -> MP1 'One f (Alias ak α x)
forall b c a (q :: Multiplicity) (m :: Multiplicity)
       (n :: Multiplicity).
(b %1 -> c) %q -> (a %1 -> b) %m -> a %n -> c
. Alias ak α (f x) %1 -> f (Alias ak α x)
forall (ak :: AliasKind) (α :: Lifetime) x.
Alias ak α (f x) %1 -> f (Alias ak α x)
forall (f :: * -> *) (ak :: AliasKind) (α :: Lifetime) x.
GDistributeAlias f =>
Alias ak α (f x) %1 -> f (Alias ak α x)
gdistributeAlias (Alias ak α (f x) %1 -> f (Alias ak α x))
-> (Alias ak α (MP1 'One f x) %1 -> Alias ak α (f x))
-> Alias ak α (MP1 'One f x)
%1 -> f (Alias ak α x)
forall b c a (q :: Multiplicity) (m :: Multiplicity)
       (n :: Multiplicity).
(b %1 -> c) %q -> (a %1 -> b) %m -> a %n -> c
. f x -> Alias ak α (f x)
forall (ak :: AliasKind) (α :: Lifetime) a. a -> Alias ak α a
UnsafeAlias (f x %1 -> Alias ak α (f x))
-> (Alias ak α (MP1 'One f x) %1 -> f x)
-> Alias ak α (MP1 'One f x)
%1 -> Alias ak α (f x)
forall b c a (q :: Multiplicity) (m :: Multiplicity)
       (n :: Multiplicity).
(b %1 -> c) %q -> (a %1 -> b) %m -> a %n -> c
. MP1 'One f x %1 -> f x
forall {k} (m :: Multiplicity) (f :: k -> *) (a :: k)
       (n :: Multiplicity).
MP1 m f a %n -> f a
unMP1 (MP1 'One f x %1 -> f x)
-> (Alias ak α (MP1 'One f x) %1 -> MP1 'One f x)
-> Alias ak α (MP1 'One f x)
%1 -> f x
forall b c a (q :: Multiplicity) (m :: Multiplicity)
       (n :: Multiplicity).
(b %1 -> c) %q -> (a %1 -> b) %m -> a %n -> c
. Alias ak α (MP1 'One f x) %1 -> MP1 'One f x
forall (ak :: AliasKind) (α :: Lifetime) a. Alias ak α a %1 -> a
unsafeUnalias

instance (GDistributeAlias f) => GDistributeAlias (M1 i c f) where
  {-# INLINE gdistributeAlias #-}
  gdistributeAlias :: forall (ak :: AliasKind) (α :: Lifetime) x.
Alias ak α (M1 i c f x) %1 -> M1 i c f (Alias ak α x)
gdistributeAlias (UnsafeAlias (M1 f x
x)) =
    f (Alias ak α x) -> M1 i c f (Alias ak α x)
forall k i (c :: Meta) (f :: k -> *) (p :: k). f p -> M1 i c f p
M1 (f (Alias ak α x) %1 -> M1 i c f (Alias ak α x))
-> f (Alias ak α x) %1 -> M1 i c f (Alias ak α x)
forall a b (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b) %q -> a %p -> b
$ Alias ak α (f x) %1 -> f (Alias ak α x)
forall (ak :: AliasKind) (α :: Lifetime) x.
Alias ak α (f x) %1 -> f (Alias ak α x)
forall (f :: * -> *) (ak :: AliasKind) (α :: Lifetime) x.
GDistributeAlias f =>
Alias ak α (f x) %1 -> f (Alias ak α x)
gdistributeAlias (Alias ak α (f x) %1 -> f (Alias ak α x))
-> Alias ak α (f x) %1 -> f (Alias ak α x)
forall a b (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b) %q -> a %p -> b
$ f x -> Alias ak α (f x)
forall (ak :: AliasKind) (α :: Lifetime) a. a -> Alias ak α a
UnsafeAlias f x
x

instance DistributesAlias Par1 where
  {-# INLINE split_ #-}
  split_ :: forall (ak :: AliasKind) (α :: Lifetime) x.
Alias ak α (Par1 x) %1 -> Par1 (Alias ak α x)
split_ (UnsafeAlias (Par1 x
a)) = Alias ak α x -> Par1 (Alias ak α x)
forall p. p -> Par1 p
Par1 (x -> Alias ak α x
forall (ak :: AliasKind) (α :: Lifetime) a. a -> Alias ak α a
UnsafeAlias x
a)

instance
  ( DistributesAlias f
  , DistributesAlias g
  , Data.Functor f
  ) =>
  GDistributeAlias (f :.: g)
  where
  {-# INLINE gdistributeAlias #-}
  gdistributeAlias :: forall (ak :: AliasKind) (α :: Lifetime) x.
Alias ak α ((:.:) f g x) %1 -> (:.:) f g (Alias ak α x)
gdistributeAlias (UnsafeAlias (Comp1 !f (g x)
fg)) =
    f (g (Alias ak α x)) -> (:.:) f g (Alias ak α x)
forall k2 k1 (f :: k2 -> *) (g :: k1 -> k2) (x :: k1).
f (g x) -> (:.:) f g x
Comp1 (f (g (Alias ak α x)) %1 -> (:.:) f g (Alias ak α x))
-> f (g (Alias ak α x)) %1 -> (:.:) f g (Alias ak α x)
forall a b (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b) %q -> a %p -> b
$ (Alias ak α (g x) %1 -> g (Alias ak α x))
-> f (Alias ak α (g x)) %1 -> f (g (Alias ak α x))
forall a b. (a %1 -> b) -> f a %1 -> f b
forall (f :: * -> *) a b. Functor f => (a %1 -> b) -> f a %1 -> f b
Data.fmap Alias ak α (g x) %1 -> g (Alias ak α x)
forall (ak :: AliasKind) (α :: Lifetime) x.
Alias ak α (g x) %1 -> g (Alias ak α x)
forall (f :: * -> *) (ak :: AliasKind) (α :: Lifetime) x.
DistributesAlias f =>
Alias ak α (f x) %1 -> f (Alias ak α x)
split_ (f (Alias ak α (g x)) %1 -> f (g (Alias ak α x)))
-> f (Alias ak α (g x)) %1 -> f (g (Alias ak α x))
forall a b (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b) %q -> a %p -> b
$ Alias ak α (f (g x)) %1 -> f (Alias ak α (g x))
forall (ak :: AliasKind) (α :: Lifetime) x.
Alias ak α (f x) %1 -> f (Alias ak α x)
forall (f :: * -> *) (ak :: AliasKind) (α :: Lifetime) x.
DistributesAlias f =>
Alias ak α (f x) %1 -> f (Alias ak α x)
split_ (Alias ak α (f (g x)) %1 -> f (Alias ak α (g x)))
-> Alias ak α (f (g x)) %1 -> f (Alias ak α (g x))
forall a b (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b) %q -> a %p -> b
$ f (g x) -> Alias ak α (f (g x))
forall (ak :: AliasKind) (α :: Lifetime) a. a -> Alias ak α a
UnsafeAlias f (g x)
fg

instance GDistributeAlias Par1 where
  {-# INLINE gdistributeAlias #-}
  gdistributeAlias :: forall (ak :: AliasKind) (α :: Lifetime) x.
Alias ak α (Par1 x) %1 -> Par1 (Alias ak α x)
gdistributeAlias (UnsafeAlias (Par1 !x
a)) = Alias ak α x -> Par1 (Alias ak α x)
forall p. p -> Par1 p
Par1 (x -> Alias ak α x
forall (ak :: AliasKind) (α :: Lifetime) a. a -> Alias ak α a
UnsafeAlias x
a)

instance
  (Unsatisfiable (Text "A type containing non-parametric field with type `" :<>: ShowType c :<>: Text "', which cannot be safely splitted!")) =>
  GDistributeAlias (K1 i c)
  where
  {-# INLINE gdistributeAlias #-}
  gdistributeAlias :: forall (ak :: AliasKind) (α :: Lifetime) x.
Alias ak α (K1 i c x) %1 -> K1 i c (Alias ak α x)
gdistributeAlias = Alias ak α (K1 i c x) %1 -> K1 i c (Alias ak α x)
forall a. Bottom => a
unsatisfiable

instance GDistributeAlias U1 where
  gdistributeAlias :: forall (ak :: AliasKind) (α :: Lifetime) x.
Alias ak α (U1 x) %1 -> U1 (Alias ak α x)
gdistributeAlias = Alias ak α (U1 x) %1 -> U1 (Alias ak α x)
forall a b. Coercible a b => a %1 -> b
coerceLin
  {-# INLINE gdistributeAlias #-}