linear-base-0.1.0: Standard library for linear types.
Safe HaskellSafe-Inferred
LanguageHaskell2010

Data.Unrestricted.Linear

Description

This module provides essential tools for doing non-linear things in linear code.

Critical Definition: Restricted

In a linear function f :: a %1-> b, the argument a must be used in a linear way. Its use is restricted while an argument in a non-linear function is unrestricted.

Hence, a linear function with an argument of Ur a (Ur is short for unrestricted) can use the a in an unrestricted way. That is, we have the following equivalence:

(Ur a %1-> b) ≌ (a -> b)

Consumable, Dupable, Moveable classes

Use these classes to perform some non-linear action on linearly bound values.

If a type is Consumable, you can consume it in a linear function that doesn't need that value to produce it's result:

first :: Consumable b => (a,b) %1-> a
first (a,b) = withConsume (consume b) a
  where
    withConsume :: () %1-> a %1-> a
    withConsume () x = x

If a type is Dupable, you can duplicate it as much as you like.

-- checkIndex ix size_of_array
checkIndex :: Int %1-> Int %1-> Bool
checkIndex ix size = withDuplicate (dup2 ix) size
  where
    withDuplicate :: (Int, Int) %1-> Int %1-> Bool
    withDuplicate (ix,ix') size = (0 <= ix) && (ix < size)
    (<) :: Int %1-> Int %1-> Bool
    (<) = ...

    (<=) :: Int %1-> Int %1-> Bool
    (<=) = ...

    (&&) :: Bool %1-> Bool %1-> Bool
    (&&) = ...

If a type is Moveable, you can move it inside Ur and use it in any non-linear way you would like.

diverge :: Int %1-> Bool
diverge ix = fromMove (move ix)
  where
    fromMove :: Ur Int %1-> Bool
    fromMove (Ur 0) = True
    fromMove (Ur 1) = True
    fromMove (Ur x) = False
Synopsis

Unrestricted

data Ur a where Source #

Ur a represents unrestricted values of type a in a linear context. The key idea is that because the contructor holds a with a regular arrow, a function that uses Ur a linearly can use a however it likes. > someLinear :: Ur a %1-> (a,a) > someLinear (Ur a) = (a,a)

Constructors

Ur :: a -> Ur a 

Instances

Instances details
Functor Ur Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

fmap :: (a -> b) -> Ur a -> Ur b #

(<$) :: a -> Ur b -> Ur a #

Applicative Ur Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

pure :: a -> Ur a #

(<*>) :: Ur (a -> b) -> Ur a -> Ur b #

liftA2 :: (a -> b -> c) -> Ur a -> Ur b -> Ur c #

(*>) :: Ur a -> Ur b -> Ur b #

(<*) :: Ur a -> Ur b -> Ur a #

Foldable Ur Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

fold :: Monoid m => Ur m -> m #

foldMap :: Monoid m => (a -> m) -> Ur a -> m #

foldMap' :: Monoid m => (a -> m) -> Ur a -> m #

foldr :: (a -> b -> b) -> b -> Ur a -> b #

foldr' :: (a -> b -> b) -> b -> Ur a -> b #

foldl :: (b -> a -> b) -> b -> Ur a -> b #

foldl' :: (b -> a -> b) -> b -> Ur a -> b #

foldr1 :: (a -> a -> a) -> Ur a -> a #

foldl1 :: (a -> a -> a) -> Ur a -> a #

toList :: Ur a -> [a] #

null :: Ur a -> Bool #

length :: Ur a -> Int #

elem :: Eq a => a -> Ur a -> Bool #

maximum :: Ord a => Ur a -> a #

minimum :: Ord a => Ur a -> a #

sum :: Num a => Ur a -> a #

product :: Num a => Ur a -> a #

Traversable Ur Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

traverse :: Applicative f => (a -> f b) -> Ur a -> f (Ur b) #

sequenceA :: Applicative f => Ur (f a) -> f (Ur a) #

mapM :: Monad m => (a -> m b) -> Ur a -> m (Ur b) #

sequence :: Monad m => Ur (m a) -> m (Ur a) #

Functor Ur Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

fmap :: (a %1 -> b) -> Ur a %1 -> Ur b Source #

Applicative Ur Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

pure :: a -> Ur a Source #

(<*>) :: Ur (a %1 -> b) %1 -> Ur a %1 -> Ur b Source #

liftA2 :: (a %1 -> b %1 -> c) -> Ur a %1 -> Ur b %1 -> Ur c Source #

Storable a => Storable (Ur a) Source # 
Instance details

Defined in Foreign.Marshal.Pure

Methods

sizeOf :: Ur a -> Int #

alignment :: Ur a -> Int #

peekElemOff :: Ptr (Ur a) -> Int -> IO (Ur a) #

pokeElemOff :: Ptr (Ur a) -> Int -> Ur a -> IO () #

peekByteOff :: Ptr b -> Int -> IO (Ur a) #

pokeByteOff :: Ptr b -> Int -> Ur a -> IO () #

peek :: Ptr (Ur a) -> IO (Ur a) #

poke :: Ptr (Ur a) -> Ur a -> IO () #

Consumable (Ur a) Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

consume :: Ur a %1 -> () Source #

Dupable (Ur a) Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

dupV :: forall (n :: Nat). KnownNat n => Ur a %1 -> V n (Ur a) Source #

dup2 :: Ur a %1 -> (Ur a, Ur a) Source #

Movable (Ur a) Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

move :: Ur a %1 -> Ur (Ur a) Source #

Eq a => Eq (Ur a) Source # 
Instance details

Defined in Data.Ord.Linear.Internal.Eq

Methods

(==) :: Ur a %1 -> Ur a %1 -> Bool Source #

(/=) :: Ur a %1 -> Ur a %1 -> Bool Source #

Ord a => Ord (Ur a) Source # 
Instance details

Defined in Data.Ord.Linear.Internal.Ord

Methods

compare :: Ur a %1 -> Ur a %1 -> Ordering Source #

(<=) :: Ur a %1 -> Ur a %1 -> Bool Source #

(<) :: Ur a %1 -> Ur a %1 -> Bool Source #

(>) :: Ur a %1 -> Ur a %1 -> Bool Source #

(>=) :: Ur a %1 -> Ur a %1 -> Bool Source #

KnownRepresentable a => KnownRepresentable (Ur a) Source # 
Instance details

Defined in Foreign.Marshal.Pure

Methods

storable :: Dict (Storable (Ur a))

unur :: Ur a %1 -> a Source #

Get an a out of an Ur a. If you call this function on a linearly bound Ur a, then the a you get out has to be used linearly, for example:

restricted :: Ur a %1-> b
restricted x = f (unur x)
  where
    -- f __must__ be linear
    f :: a %1-> b
    f x = ...

lift :: (a -> b) -> Ur a %1 -> Ur b Source #

Lifts a function on a linear Ur a.

lift2 :: (a -> b -> c) -> Ur a %1 -> Ur b %1 -> Ur c Source #

Lifts a function to work on two linear Ur a.

Performing non-linear actions on linearly bound values

class Consumable a where Source #

Methods

consume :: a %1 -> () Source #

Instances

Instances details
Consumable Bool Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

consume :: Bool %1 -> () Source #

Consumable Char Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

consume :: Char %1 -> () Source #

Consumable Double Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

consume :: Double %1 -> () Source #

Consumable Int Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

consume :: Int %1 -> () Source #

Consumable Ordering Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

consume :: Ordering %1 -> () Source #

Consumable () Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

consume :: () %1 -> () Source #

Consumable Any Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

consume :: Any %1 -> () Source #

Consumable All Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

consume :: All %1 -> () Source #

Consumable Pool Source # 
Instance details

Defined in Foreign.Marshal.Pure

Methods

consume :: Pool %1 -> () Source #

Consumable a => Consumable [a] Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

consume :: [a] %1 -> () Source #

Consumable a => Consumable (Maybe a) Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

consume :: Maybe a %1 -> () Source #

Consumable a => Consumable (Sum a) Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

consume :: Sum a %1 -> () Source #

Consumable a => Consumable (Product a) Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

consume :: Product a %1 -> () Source #

Consumable a => Consumable (NonEmpty a) Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

consume :: NonEmpty a %1 -> () Source #

Consumable (Ur a) Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

consume :: Ur a %1 -> () Source #

Consumable (Array a) Source # 
Instance details

Defined in Data.Array.Mutable.Linear

Methods

consume :: Array a %1 -> () Source #

Consumable (Vector a) Source # 
Instance details

Defined in Data.Vector.Mutable.Linear

Methods

consume :: Vector a %1 -> () Source #

Consumable (Set a) Source # 
Instance details

Defined in Data.Set.Mutable.Linear

Methods

consume :: Set a %1 -> () Source #

(Consumable a, Consumable b) => Consumable (Either a b) Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

consume :: Either a b %1 -> () Source #

(Consumable a, Consumable b) => Consumable (a, b) Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

consume :: (a, b) %1 -> () Source #

Consumable (HashMap k v) Source # 
Instance details

Defined in Data.HashMap.Mutable.Linear

Methods

consume :: HashMap k v %1 -> () Source #

(Consumable a, Consumable b, Consumable c) => Consumable (a, b, c) Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

consume :: (a, b, c) %1 -> () Source #

class Consumable a => Dupable a where Source #

The laws of Dupable are dual to those of Monoid:

  • first consume (dup2 a) ≃ a ≃ second consume (dup2 a) (neutrality)
  • first dup2 (dup2 a) ≃ (second dup2 (dup2 a)) (associativity)

Where the (≃) sign represents equality up to type isomorphism.

When implementing Dupable instances for composite types, using dupV should be more convenient since V has a zipping Applicative instance.

Minimal complete definition

dupV | dup2

Methods

dupV :: forall n. KnownNat n => a %1 -> V n a Source #

dup2 :: a %1 -> (a, a) Source #

Instances

Instances details
Dupable Bool Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

dupV :: forall (n :: Nat). KnownNat n => Bool %1 -> V n Bool Source #

dup2 :: Bool %1 -> (Bool, Bool) Source #

Dupable Char Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

dupV :: forall (n :: Nat). KnownNat n => Char %1 -> V n Char Source #

dup2 :: Char %1 -> (Char, Char) Source #

Dupable Double Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

dupV :: forall (n :: Nat). KnownNat n => Double %1 -> V n Double Source #

dup2 :: Double %1 -> (Double, Double) Source #

Dupable Int Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

dupV :: forall (n :: Nat). KnownNat n => Int %1 -> V n Int Source #

dup2 :: Int %1 -> (Int, Int) Source #

Dupable Ordering Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

dupV :: forall (n :: Nat). KnownNat n => Ordering %1 -> V n Ordering Source #

dup2 :: Ordering %1 -> (Ordering, Ordering) Source #

Dupable () Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

dupV :: forall (n :: Nat). KnownNat n => () %1 -> V n () Source #

dup2 :: () %1 -> ((), ()) Source #

Dupable Any Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

dupV :: forall (n :: Nat). KnownNat n => Any %1 -> V n Any Source #

dup2 :: Any %1 -> (Any, Any) Source #

Dupable All Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

dupV :: forall (n :: Nat). KnownNat n => All %1 -> V n All Source #

dup2 :: All %1 -> (All, All) Source #

Dupable Pool Source # 
Instance details

Defined in Foreign.Marshal.Pure

Methods

dupV :: forall (n :: Nat). KnownNat n => Pool %1 -> V n Pool Source #

dup2 :: Pool %1 -> (Pool, Pool) Source #

Dupable a => Dupable [a] Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

dupV :: forall (n :: Nat). KnownNat n => [a] %1 -> V n [a] Source #

dup2 :: [a] %1 -> ([a], [a]) Source #

Dupable a => Dupable (Maybe a) Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

dupV :: forall (n :: Nat). KnownNat n => Maybe a %1 -> V n (Maybe a) Source #

dup2 :: Maybe a %1 -> (Maybe a, Maybe a) Source #

Dupable a => Dupable (Sum a) Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

dupV :: forall (n :: Nat). KnownNat n => Sum a %1 -> V n (Sum a) Source #

dup2 :: Sum a %1 -> (Sum a, Sum a) Source #

Dupable a => Dupable (Product a) Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

dupV :: forall (n :: Nat). KnownNat n => Product a %1 -> V n (Product a) Source #

dup2 :: Product a %1 -> (Product a, Product a) Source #

Dupable a => Dupable (NonEmpty a) Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

dupV :: forall (n :: Nat). KnownNat n => NonEmpty a %1 -> V n (NonEmpty a) Source #

dup2 :: NonEmpty a %1 -> (NonEmpty a, NonEmpty a) Source #

Dupable (Ur a) Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

dupV :: forall (n :: Nat). KnownNat n => Ur a %1 -> V n (Ur a) Source #

dup2 :: Ur a %1 -> (Ur a, Ur a) Source #

Dupable (Array a) Source # 
Instance details

Defined in Data.Array.Mutable.Linear

Methods

dupV :: forall (n :: Nat). KnownNat n => Array a %1 -> V n (Array a) Source #

dup2 :: Array a %1 -> (Array a, Array a) Source #

Dupable (Vector a) Source # 
Instance details

Defined in Data.Vector.Mutable.Linear

Methods

dupV :: forall (n :: Nat). KnownNat n => Vector a %1 -> V n (Vector a) Source #

dup2 :: Vector a %1 -> (Vector a, Vector a) Source #

Dupable (Set a) Source # 
Instance details

Defined in Data.Set.Mutable.Linear

Methods

dupV :: forall (n :: Nat). KnownNat n => Set a %1 -> V n (Set a) Source #

dup2 :: Set a %1 -> (Set a, Set a) Source #

(Dupable a, Dupable b) => Dupable (Either a b) Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

dupV :: forall (n :: Nat). KnownNat n => Either a b %1 -> V n (Either a b) Source #

dup2 :: Either a b %1 -> (Either a b, Either a b) Source #

(Dupable a, Dupable b) => Dupable (a, b) Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

dupV :: forall (n :: Nat). KnownNat n => (a, b) %1 -> V n (a, b) Source #

dup2 :: (a, b) %1 -> ((a, b), (a, b)) Source #

Dupable (HashMap k v) Source # 
Instance details

Defined in Data.HashMap.Mutable.Linear

Methods

dupV :: forall (n :: Nat). KnownNat n => HashMap k v %1 -> V n (HashMap k v) Source #

dup2 :: HashMap k v %1 -> (HashMap k v, HashMap k v) Source #

(Dupable a, Dupable b, Dupable c) => Dupable (a, b, c) Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

dupV :: forall (n :: Nat). KnownNat n => (a, b, c) %1 -> V n (a, b, c) Source #

dup2 :: (a, b, c) %1 -> ((a, b, c), (a, b, c)) Source #

class Dupable a => Movable a where Source #

Use Movable a to represent a type which can be used many times even when given linearly. Simple data types such as Bool or [] are Movable. Though, bear in mind that this typically induces a deep copy of the value.

Formally, Movable a is the class of coalgebras of the Ur comonad. That is

  • unur (move x) = x
  • @move @(Ur a) (move @a x) = fmap (move @a) $ move @a x

Additionally, a Movable instance must be compatible with its Dupable parent instance. That is:

  • case move x of {Ur _ -> ()} = consume x
  • case move x of {Ur x -> (x, x)} = dup2 x

Methods

move :: a %1 -> Ur a Source #

Instances

Instances details
Movable Bool Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

move :: Bool %1 -> Ur Bool Source #

Movable Char Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

move :: Char %1 -> Ur Char Source #

Movable Double Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

move :: Double %1 -> Ur Double Source #

Movable Int Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

move :: Int %1 -> Ur Int Source #

Movable Ordering Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

move :: Ordering %1 -> Ur Ordering Source #

Movable () Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

move :: () %1 -> Ur () Source #

Movable Any Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

move :: Any %1 -> Ur Any Source #

Movable All Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

move :: All %1 -> Ur All Source #

Movable a => Movable [a] Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

move :: [a] %1 -> Ur [a] Source #

Movable a => Movable (Maybe a) Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

move :: Maybe a %1 -> Ur (Maybe a) Source #

Movable a => Movable (Sum a) Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

move :: Sum a %1 -> Ur (Sum a) Source #

Movable a => Movable (Product a) Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

move :: Product a %1 -> Ur (Product a) Source #

Movable a => Movable (NonEmpty a) Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

move :: NonEmpty a %1 -> Ur (NonEmpty a) Source #

Movable (Ur a) Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

move :: Ur a %1 -> Ur (Ur a) Source #

(Movable a, Movable b) => Movable (Either a b) Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

move :: Either a b %1 -> Ur (Either a b) Source #

(Movable a, Movable b) => Movable (a, b) Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

move :: (a, b) %1 -> Ur (a, b) Source #

(Movable a, Movable b, Movable c) => Movable (a, b, c) Source # 
Instance details

Defined in Data.Unrestricted.Internal.Instances

Methods

move :: (a, b, c) %1 -> Ur (a, b, c) Source #

lseq :: Consumable a => a %1 -> b %1 -> b Source #

Consume the first argument and return the second argument. This is like seq but the first argument is restricted to be Consumable.

dup :: Dupable a => a %1 -> (a, a) Source #

dup3 :: Dupable a => a %1 -> (a, a, a) Source #