{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE LinearTypes #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneKindSignatures #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UnboxedTuples #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# OPTIONS_HADDOCK hide #-}
module Data.Replicator.Linear.Internal
( Replicator (..),
consume,
duplicate,
map,
pure,
(<*>),
liftA2,
next,
next#,
take,
extract,
extend,
Elim,
elim,
)
where
import Data.Arity.Linear.Internal
import Data.Kind (Constraint, Type)
import Data.Replicator.Linear.Internal.ReplicationStream (ReplicationStream (..))
import qualified Data.Replicator.Linear.Internal.ReplicationStream as ReplicationStream
import GHC.TypeLits
import Prelude.Linear.Internal
import Prelude ((-))
import qualified Prelude
data Replicator a where
Moved :: a -> Replicator a
Streamed :: ReplicationStream a %1 -> Replicator a
consume :: Replicator a %1 -> ()
consume :: forall a. Replicator a %1 -> ()
consume (Moved a
_) = ()
consume (Streamed ReplicationStream a
stream) = forall a. ReplicationStream a %1 -> ()
ReplicationStream.consume ReplicationStream a
stream
{-# INLINEABLE consume #-}
duplicate :: Replicator a %1 -> Replicator (Replicator a)
duplicate :: forall a. Replicator a %1 -> Replicator (Replicator a)
duplicate = \case
Moved a
x -> forall a. a -> Replicator a
Moved (forall a. a -> Replicator a
Moved a
x)
Streamed ReplicationStream a
stream -> forall a. ReplicationStream a -> Replicator a
Streamed forall a b (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b) %q -> a %p -> b
$ forall a b.
(a %1 -> b) -> ReplicationStream a %1 -> ReplicationStream b
ReplicationStream.map forall a. ReplicationStream a -> Replicator a
Streamed (forall a.
ReplicationStream a %1 -> ReplicationStream (ReplicationStream a)
ReplicationStream.duplicate ReplicationStream a
stream)
map :: (a %1 -> b) -> Replicator a %1 -> Replicator b
map :: forall a b. (a %1 -> b) -> Replicator a %1 -> Replicator b
map a %1 -> b
f = \case
Moved a
x -> forall a. a -> Replicator a
Moved (a %1 -> b
f a
x)
Streamed ReplicationStream a
stream -> forall a. ReplicationStream a -> Replicator a
Streamed forall a b (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b) %q -> a %p -> b
$ forall a b.
(a %1 -> b) -> ReplicationStream a %1 -> ReplicationStream b
ReplicationStream.map a %1 -> b
f ReplicationStream a
stream
pure :: a -> Replicator a
pure :: forall a. a -> Replicator a
pure = forall a. a -> Replicator a
Moved
(<*>) :: Replicator (a %1 -> b) %1 -> Replicator a %1 -> Replicator b
Moved a %1 -> b
f <*> :: forall a b.
Replicator (a %1 -> b) %1 -> Replicator a %1 -> Replicator b
<*> Moved a
x = forall a. a -> Replicator a
Moved (a %1 -> b
f a
x)
Moved a %1 -> b
f <*> Streamed ReplicationStream a
s = forall a. ReplicationStream a -> Replicator a
Streamed (forall a b.
(a %1 -> b) -> ReplicationStream a %1 -> ReplicationStream b
ReplicationStream.map a %1 -> b
f ReplicationStream a
s)
Streamed ReplicationStream (a %1 -> b)
fs <*> Moved a
x = forall a. ReplicationStream a -> Replicator a
Streamed (forall a b.
(a %1 -> b) -> ReplicationStream a %1 -> ReplicationStream b
ReplicationStream.map (\a %1 -> b
f -> a %1 -> b
f a
x) ReplicationStream (a %1 -> b)
fs)
Streamed ReplicationStream (a %1 -> b)
sf <*> Streamed ReplicationStream a
sx = forall a. ReplicationStream a -> Replicator a
Streamed (ReplicationStream (a %1 -> b)
sf forall a b.
ReplicationStream (a %1 -> b)
%1 -> ReplicationStream a %1 -> ReplicationStream b
ReplicationStream.<*> ReplicationStream a
sx)
infixl 4 <*>
liftA2 :: (a %1 -> b %1 -> c) -> Replicator a %1 -> Replicator b %1 -> Replicator c
liftA2 :: forall a b c.
(a %1 -> b %1 -> c)
-> Replicator a %1 -> Replicator b %1 -> Replicator c
liftA2 a %1 -> b %1 -> c
f (Moved a
a) (Moved b
b) = forall a. a -> Replicator a
Moved (a %1 -> b %1 -> c
f a
a b
b)
liftA2 a %1 -> b %1 -> c
f (Moved a
a) (Streamed ReplicationStream b
s) = forall a. ReplicationStream a -> Replicator a
Streamed (forall a b.
(a %1 -> b) -> ReplicationStream a %1 -> ReplicationStream b
ReplicationStream.map (a %1 -> b %1 -> c
f a
a) ReplicationStream b
s)
liftA2 a %1 -> b %1 -> c
f (Streamed ReplicationStream a
s) (Moved b
b) = forall a. ReplicationStream a -> Replicator a
Streamed (forall a b.
(a %1 -> b) -> ReplicationStream a %1 -> ReplicationStream b
ReplicationStream.map (\a
a -> a %1 -> b %1 -> c
f a
a b
b) ReplicationStream a
s)
liftA2 a %1 -> b %1 -> c
f (Streamed ReplicationStream a
sa) (Streamed ReplicationStream b
sb) = forall a. ReplicationStream a -> Replicator a
Streamed (forall a b c.
(a %1 -> b %1 -> c)
-> ReplicationStream a
%1 -> ReplicationStream b
%1 -> ReplicationStream c
ReplicationStream.liftA2 a %1 -> b %1 -> c
f ReplicationStream a
sa ReplicationStream b
sb)
{-# INLINE liftA2 #-}
next :: Replicator a %1 -> (a, Replicator a)
next :: forall a. Replicator a %1 -> (a, Replicator a)
next (Moved a
x) = (a
x, forall a. a -> Replicator a
Moved a
x)
next (Streamed (ReplicationStream s
s s %1 -> a
give s %1 -> (s, s)
dups s %1 -> ()
consumes)) =
s %1 -> (s, s)
dups s
s forall a b (p :: Multiplicity) (q :: Multiplicity).
a %p -> (a %p -> b) %q -> b
& \case
(s
s1, s
s2) -> (s %1 -> a
give s
s1, forall a. ReplicationStream a -> Replicator a
Streamed (forall s a.
s
-> (s %1 -> a)
-> (s %1 -> (s, s))
-> (s %1 -> ())
-> ReplicationStream a
ReplicationStream s
s2 s %1 -> a
give s %1 -> (s, s)
dups s %1 -> ()
consumes))
{-# INLINEABLE next #-}
next# :: Replicator a %1 -> (# a, Replicator a #)
next# :: forall a. Replicator a %1 -> (# a, Replicator a #)
next# (Moved a
x) = (# a
x, forall a. a -> Replicator a
Moved a
x #)
next# (Streamed (ReplicationStream s
s s %1 -> a
give s %1 -> (s, s)
dups s %1 -> ()
consumes)) =
s %1 -> (s, s)
dups s
s forall a b (p :: Multiplicity) (q :: Multiplicity).
a %p -> (a %p -> b) %q -> b
& \case
(s
s1, s
s2) -> (# s %1 -> a
give s
s1, forall a. ReplicationStream a -> Replicator a
Streamed (forall s a.
s
-> (s %1 -> a)
-> (s %1 -> (s, s))
-> (s %1 -> ())
-> ReplicationStream a
ReplicationStream s
s2 s %1 -> a
give s %1 -> (s, s)
dups s %1 -> ()
consumes) #)
{-# INLINEABLE next# #-}
take :: Prelude.Int -> Replicator a %1 -> [a]
take :: forall a. Int -> Replicator a %1 -> [a]
take Int
0 Replicator a
r =
forall a. Replicator a %1 -> ()
consume Replicator a
r forall a b (p :: Multiplicity) (q :: Multiplicity).
a %p -> (a %p -> b) %q -> b
& \case
() -> []
take Int
1 Replicator a
r = [forall a. Replicator a %1 -> a
extract Replicator a
r]
take Int
n Replicator a
r =
forall a. Replicator a %1 -> (a, Replicator a)
next Replicator a
r forall a b (p :: Multiplicity) (q :: Multiplicity).
a %p -> (a %p -> b) %q -> b
& \case
(a
a, Replicator a
r') -> a
a forall a. a -> [a] -> [a]
: forall a. Int -> Replicator a %1 -> [a]
take (Int
n forall a. Num a => a -> a -> a
- Int
1) Replicator a
r'
extract :: Replicator a %1 -> a
(Moved a
x) = a
x
extract (Streamed (ReplicationStream s
s s %1 -> a
give s %1 -> (s, s)
_ s %1 -> ()
_)) = s %1 -> a
give s
s
{-# INLINEABLE extract #-}
extend :: (Replicator a %1 -> b) -> Replicator a %1 -> Replicator b
extend :: forall a b.
(Replicator a %1 -> b) -> Replicator a %1 -> Replicator b
extend Replicator a %1 -> b
f = forall a b. (a %1 -> b) -> Replicator a %1 -> Replicator b
map Replicator a %1 -> b
f forall b c a (q :: Multiplicity) (m :: Multiplicity)
(n :: Multiplicity).
(b %1 -> c) %q -> (a %1 -> b) %m -> a %n -> c
. forall a. Replicator a %1 -> Replicator (Replicator a)
duplicate
elim ::
forall (n :: Nat) a b f.
( Elim (NatToPeano n) a b,
IsFunN a b f,
f ~ FunN (NatToPeano n) a b,
n ~ Arity b f
) =>
f %1 ->
Replicator a %1 ->
b
elim :: forall (n :: Nat) a b f.
(Elim (NatToPeano n) a b, IsFunN a b f,
f ~ FunN (NatToPeano n) a b, n ~ Arity b f) =>
f %1 -> Replicator a %1 -> b
elim f
f Replicator a
r = forall (n :: Peano) a b.
Elim n a b =>
FunN n a b %1 -> Replicator a %1 -> b
elim' @(NatToPeano n) f
f Replicator a
r
type Elim :: Peano -> Type -> Type -> Constraint
class Elim n a b where
elim' :: FunN n a b %1 -> Replicator a %1 -> b
instance Elim 'Z a b where
elim' :: FunN 'Z a b %1 -> Replicator a %1 -> b
elim' FunN 'Z a b
b Replicator a
r =
forall a. Replicator a %1 -> ()
consume Replicator a
r forall a b (p :: Multiplicity) (q :: Multiplicity).
a %p -> (a %p -> b) %q -> b
& \case
() -> FunN 'Z a b
b
{-# INLINE elim' #-}
instance Elim ('S 'Z) a b where
elim' :: FunN ('S 'Z) a b %1 -> Replicator a %1 -> b
elim' FunN ('S 'Z) a b
f Replicator a
r = FunN ('S 'Z) a b
f (forall a. Replicator a %1 -> a
extract Replicator a
r)
{-# INLINE elim' #-}
instance (Elim ('S n) a b) => Elim ('S ('S n)) a b where
elim' :: FunN ('S ('S n)) a b %1 -> Replicator a %1 -> b
elim' FunN ('S ('S n)) a b
g Replicator a
r =
forall a. Replicator a %1 -> (a, Replicator a)
next Replicator a
r forall a b (p :: Multiplicity) (q :: Multiplicity).
a %p -> (a %p -> b) %q -> b
& \case
(a
a, Replicator a
r') -> forall (n :: Peano) a b.
Elim n a b =>
FunN n a b %1 -> Replicator a %1 -> b
elim' @('S n) (FunN ('S ('S n)) a b
g a
a) Replicator a
r'
{-# INLINE elim' #-}