packages feed

linear-base 0.5.0 → 0.8.1

raw patch · 20 files changed

Files

CHANGELOG.md view
@@ -1,5 +1,41 @@ # Change Log +## [v0.8.1](https://github.com/tweag/linear-base/tree/v0.8.1) (2026-06-24)++[Full Changelog](https://github.com/tweag/linear-base/compare/v0.8.0...v0.8.1)++### Headline changes++- Restore compatibility with GHC 9.2: Import Multiplicity from GHC.Types [\#509](https://github.com/tweag/linear-base/pull/509) ([tomsmeding](https://github.com/tomsmeding))++## [v0.8.0](https://github.com/tweag/linear-base/tree/v0.8.0) (2026-05-12)++[Full Changelog](https://github.com/tweag/linear-base/compare/v0.7.0...v0.8.0)++### Headline changes++- Add MonadIO instances for StateT and ReaderT [\#506](https://github.com/tweag/linear-base/pull/506) ([dcastro](https://github.com/dcastro))+- Coerce `System.IO` and `Linear.IO` into `RIO` [\#505](https://github.com/tweag/linear-base/pull/505) ([dcastro](https://github.com/dcastro))++## [v0.7.0](https://github.com/tweag/linear-base/tree/v0.7.0) (2026-02-27)++[Full Changelog](https://github.com/tweag/linear-base/compare/v0.6.0...v0.7.0)++### Headline changes++- Add instance Consumable/Dupable/Movable for ByteString, ShortByteString and Text [\#501](https://github.com/tweag/linear-base/pull/501) ([Bodigrim](https://github.com/Bodigrim))+- feat: Adds missing instances for `NonEmpty` and adds some Linear counterpart of `Data.List.NonEmpty` [\#495](https://github.com/tweag/linear-base/pull/495) ([konn](https://github.com/konn))+- use Unsatisfiable for banned instances \(unrestricted Monoid / Semigroup for linear containers\) [\#494](https://github.com/tweag/linear-base/pull/494) ([konn](https://github.com/konn))+- Control Monad instance for linear arrows [\#493](https://github.com/tweag/linear-base/pull/493) ([konn](https://github.com/konn))++## [v0.6.0](https://github.com/tweag/linear-base/tree/v0.6.0) (2025-11-18)++[Full Changelog](https://github.com/tweag/linear-base/compare/v0.5.0...v0.6.0)++### Headline changes++- Make List.zipWith as lazy as expected [\#492](https://github.com/tweag/linear-base/pull/492) ([aspiwack](https://github.com/aspiwack))+ ## [v0.5.0](https://github.com/tweag/linear-base/tree/v0.5.0) (2025-04-07)  [Full Changelog](https://github.com/tweag/linear-base/compare/v0.4.0...v0.5.0)
bench/Data/Mutable/HashMap.hs view
@@ -22,7 +22,7 @@ import qualified Data.HashTable.ST.Basic as BasicST import qualified Data.HashTable.ST.Cuckoo as CuckooST import Data.Hashable (Hashable (..), hashWithSalt)-import Data.List (foldl')+import qualified Data.List as List import qualified Data.Unrestricted.Linear as Linear import GHC.Generics (Generic) import qualified Prelude.Linear as Linear@@ -199,7 +199,7 @@       bench (descriptions !! n) $ nf (\xs -> f xs Map.empty) kvs      foldlx :: (b -> a -> b) -> [a] -> b -> b-    foldlx f xs b = foldl' f b xs+    foldlx f xs b = List.foldl' f b xs      look :: Map.HashMap Key Int -> Key -> Map.HashMap Key Int     look m k = case m Map.!? k of@@ -208,7 +208,7 @@      bench1 :: Benchmark     bench1 = mkBench 0 $-      \xs hm -> foldl' (\m (k, v) -> Map.delete k (Map.insert k v m)) hm xs+      \xs hm -> List.foldl' (\m (k, v) -> Map.delete k (Map.insert k v m)) hm xs      bench2 :: Benchmark     bench2 = mkBench 1 $
linear-base.cabal view
@@ -1,6 +1,6 @@ cabal-version:      3.0 name:               linear-base-version:            0.5.0+version:            0.8.1 license:            MIT license-file:       LICENSE copyright:          (c) Tweag Holding and affiliates@@ -79,6 +79,7 @@         Data.HashMap.Mutable.Linear         Data.HashMap.Mutable.Linear.Internal         Data.List.Linear+        Data.List.NonEmpty.Linear         Data.Maybe.Linear         Data.Monoid.Linear         Data.Monoid.Linear.Internal.Monoid@@ -134,6 +135,7 @@     default-language: Haskell2010     build-depends:         base >=4.16 && <5,+        bytestring,         containers,         ghc-prim,         ghc-bignum,
src/Control/Functor/Linear/Internal/Reader.hs view
@@ -1,5 +1,9 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DerivingVia #-}+{-# LANGUAGE FlexibleInstances #-} {-# OPTIONS -Wno-orphans #-} {-# LANGUAGE LinearTypes #-}+{-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE NoImplicitPrelude #-} {-# OPTIONS_HADDOCK hide #-} @@ -28,8 +32,10 @@ import Data.Functor.Identity import qualified Data.Functor.Linear.Internal.Applicative as Data import qualified Data.Functor.Linear.Internal.Functor as Data+import Data.Kind (FUN) import Data.Unrestricted.Linear.Internal.Consumable import Data.Unrestricted.Linear.Internal.Dupable+import GHC.Types (Multiplicity (..)) import Prelude.Linear.Internal (runIdentity', ($), (.))  -- # Linear ReaderT@@ -119,3 +125,9 @@  instance MonadTrans (NonLinear.ReaderT r) where   lift x = NonLinear.ReaderT (\_ -> x)++deriving via Reader r instance (Dupable r) => Data.Applicative (FUN 'One r)++deriving via Reader r instance (Dupable r) => Applicative (FUN 'One r)++deriving via Reader r instance (Dupable r) => Monad (FUN 'One r)
src/Control/Monad/IO/Class/Linear.hs view
@@ -7,6 +7,8 @@ import Prelude.Linear import qualified System.IO as System import qualified System.IO.Linear as Linear+import System.IO.Resource.Linear (RIO)+import qualified System.IO.Resource.Linear as RIO  -- | Like 'NonLinear.MonadIO' but allows to lift both linear -- and non-linear 'IO' actions into a linear monad.@@ -19,3 +21,12 @@  instance MonadIO Linear.IO where   liftIO = id++instance MonadIO RIO where+  liftIO = RIO.fromIO++instance (MonadIO m) => MonadIO (Linear.StateT s m) where+  liftIO = Linear.lift . liftIO++instance (MonadIO m, Dupable r) => MonadIO (Linear.ReaderT r m) where+  liftIO = Linear.lift . liftIO
src/Data/Functor/Linear/Internal/Functor.hs view
@@ -32,6 +32,7 @@ import Data.Functor.Product import Data.Functor.Sum import Data.Kind (FUN)+import Data.List.NonEmpty (NonEmpty) import Data.Unrestricted.Linear.Internal.Consumable import Data.Unrestricted.Linear.Internal.Ur import GHC.Types (Multiplicity (..))@@ -75,6 +76,11 @@       go :: [a] %1 -> [b]       go [] = []       go (a : as) = f a : go as++deriving via+  Generically1 NonEmpty+  instance+    Functor NonEmpty  deriving via   Generically1 (Const x)
src/Data/Functor/Linear/Internal/Traversable.hs view
@@ -34,6 +34,7 @@ import Data.Functor.Const import qualified Data.Functor.Linear.Internal.Applicative as Data import qualified Data.Functor.Linear.Internal.Functor as Data+import Data.List.NonEmpty (NonEmpty (..)) import GHC.Types (Multiplicity (..)) import Generics.Linear import Prelude.Linear.Internal@@ -130,6 +131,12 @@     where       go [] = Control.pure []       go (x : xs) = Control.liftA2 (:) (f x) (go xs)++instance Traversable NonEmpty where+  -- We define traverse explicitly both to allow specialization+  -- to the appropriate Applicative and to allow specialization to+  -- the passed function. The generic definition allows neither, sadly.+  traverse f (x :| xs) = (:|) Control.<$> f x Control.<*> traverse f xs  instance Traversable ((,) a) where   traverse = genericTraverse
src/Data/HashMap/Mutable/Linear/Internal.hs view
@@ -1,5 +1,7 @@ {-# LANGUAGE BangPatterns #-} {-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE InstanceSigs #-}@@ -25,7 +27,9 @@ import Data.Hashable import qualified Data.Maybe as NonLinear import Data.Unrestricted.Linear+import GHC.TypeLits (ErrorMessage (..)) import Prelude.Linear hiding (filter, insert, lookup, mapMaybe, read, (+))+import Prelude.Linear.Unsatisfiable (Unsatisfiable, unsatisfiable) import Unsafe.Coerce (unsafeCoerce) import qualified Unsafe.Linear as Unsafe import Prelude ((+))@@ -481,8 +485,8 @@         )         arr -instance Prelude.Semigroup (HashMap k v) where-  (<>) = error "Prelude.<>: invariant violation, unrestricted HashMap"+instance (Unsatisfiable ('Text "Using Prelude's Semigroup methods on a Data.HashMap.Mutable.Linear is vacuous as there can't be an unrestricted such Hashmap")) => Prelude.Semigroup (HashMap k v) where+  (<>) = unsatisfiable  instance (Keyed k) => Semigroup (HashMap k v) where   (<>) = union
src/Data/List/Linear.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE BangPatterns #-} {-# LANGUAGE LinearTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE NoImplicitPrelude #-}@@ -80,6 +80,7 @@     zip3,     zipWith,     zipWith',+    zipFold,     zipWith3,     unzip,     unzip3,@@ -354,18 +355,53 @@ zip3 = zipWith3 (,,)  zipWith :: (Consumable a, Consumable b) => (a %1 -> b %1 -> c) -> [a] %1 -> [b] %1 -> [c]-zipWith f xs ys =-  zipWith' f xs ys & \(ret, leftovers) ->-    leftovers `lseq` ret+zipWith f =+  zipFold (\a b cs -> f a b : cs) [] consume2 consume2+  where+    consume2 :: forall x y z. (Consumable x, Consumable y) => x %1 -> y %1 -> [z]+    consume2 x y = x `lseq` y `lseq` []  -- | Same as 'zipWith', but returns the leftovers instead of consuming them.+-- Because the leftovers are returned at toplevel, @zipWith'@ is pretty strict:+-- forcing the first cons cell of the returned list forces all the recursive+-- calls. zipWith' :: (a %1 -> b %1 -> c) -> [a] %1 -> [b] %1 -> ([c], Maybe (Either (NonEmpty a) (NonEmpty b)))-zipWith' _ [] [] = ([], Nothing)-zipWith' _ (a : as) [] = ([], Just (Left (a :| as)))-zipWith' _ [] (b : bs) = ([], Just (Right (b :| bs)))-zipWith' f (a : as) (b : bs) =-  case zipWith' f as bs of-    (cs, rest) -> (f a b : cs, rest)+zipWith' f =+  zipFold+    (\a b !(cs, rest) -> ((f a b : cs), rest))+    ([], Nothing)+    (\a as -> ([], Just (Left (a :| as))))+    (\b bs -> ([], Just (Right (b :| bs))))++-- | A function which combines zipping and 'foldr'. It's more general than all+-- the zip-family functions ('zip', 'zip'', 'zipWith', 'zipWith'').+--+-- If @k < n@, then+--+-- * @'zipFold' cons nil lefta leftb [a₁, a₂, …, aₙ] [b₁, b₂, …, bₖ] = cons a₁ b₁ (cons a₂ b₂ (… (cons aₖ bₖ (lefta aₖ₊₁ [aₖ₊₂, …, aₙ]))))@+-- * @'zipFold' cons nil lefta leftb [a₁, a₂, …, aₖ] [b₁, b₂, …, bₙ] = cons a₁ b₁ (cons a₂ b₂ (… (cons aₖ bₖ (leftb bₖ₊₁ [bₖ₊₂, …, bₙ]))))@+-- * @'zipFold' cons nil lefta leftb [a₁, a₂, …, aₖ] [b₁, b₂, …, bₖ] = cons a₁ b₁ (cons a₂ b₂ (… (cons aₖ bₖ nil)))@+zipFold ::+  forall r a b.+  -- | Combines elements at the same index+  (a %1 -> b %1 -> r %1 -> r) ->+  -- | Starting value if both lists have the same length+  r ->+  -- | Starting value if the first list is longer+  (a %1 -> [a] %1 -> r) ->+  -- | Starting value if the second list is longer+  (b %1 -> [b] %1 -> r) ->+  [a] %1 ->+  [b] %1 ->+  r+zipFold cons nil lefta leftb =+  go+  where+    go :: [a] %1 -> [b] %1 -> r+    go [] [] = nil+    go (a : as) [] = lefta a as+    go [] (b : bs) = leftb b bs+    go (a : as) (b : bs) = cons a b (go as bs)  zipWith3 :: forall a b c d. (Consumable a, Consumable b, Consumable c) => (a %1 -> b %1 -> c %1 -> d) -> [a] %1 -> [b] %1 -> [c] %1 -> [d] zipWith3 _ [] ys zs = (ys, zs) `lseq` []
+ src/Data/List/NonEmpty/Linear.hs view
@@ -0,0 +1,211 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE LinearTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE NoImplicitPrelude #-}+{-# OPTIONS_GHC -Wno-name-shadowing #-}+{-# OPTIONS_GHC -Wno-orphans #-}++-- |+-- Linear versions of 'NonEmpty' functions.+--+-- This module only contains minimal amount of documentation; consult the+-- original "Data.List.NonEmpty" module for more detailed information.+module Data.List.NonEmpty.Linear+  ( -- * Non-empty stream transformations+    NonEmpty (..),+    map,+    intersperse,+    scanl,+    scanr,+    scanl1,+    scanr1,+    transpose,+    NonLinear.sortBy,+    NonLinear.sortWith,++    -- * Basic functions+    length,+    NonLinear.head,+    NonLinear.tail,+    NonLinear.last,+    NonLinear.init,+    singleton,+    (<|),+    cons,+    uncons,+    unfoldr,+    NonLinear.sort,+    reverse,+    append,+    appendList,+    prependList,++    -- * Extracting sublists+    take,+    drop,+    splitAt,+    takeWhile,+    dropWhile,+    span,+    break,+    filter,+    partition,++    -- * Zipping and unzipping streams+    zip,+    zipWith,+    zip',+    zipWith',+    unzip,+    unzip3,++    -- * Converting to and from a list+    fromList,+    toList,+    nonEmpty,+    xor,+  )+where++import qualified Data.List.Linear as List+import Data.List.NonEmpty (NonEmpty (..))+import qualified Data.List.NonEmpty as NonLinear+import Data.Vector.Internal.Check (HasCallStack)+import Prelude.Linear hiding (drop, dropWhile, filter, intersperse, length, map, partition, reverse, scanl, scanl1, scanr, scanr1, span, splitAt, take, takeWhile, transpose, uncons, unfoldr, unzip, unzip3, zip, zip', zipWith, zipWith')+import qualified Unsafe.Linear as Unsafe+import qualified Prelude as Prelude++map :: (a %1 -> b) -> NonEmpty a %1 -> NonEmpty b+map f (x :| xs) = f x :| List.map f xs++intersperse :: a -> NonEmpty a %1 -> NonEmpty a+intersperse a = Unsafe.toLinear (NonLinear.intersperse a)++reverse :: NonEmpty a %1 -> NonEmpty a+reverse = Unsafe.toLinear NonLinear.reverse++scanl :: (Dupable b) => (b %1 -> a %1 -> b) -> b %1 -> NonEmpty a %1 -> NonEmpty b+scanl f z = fromList . List.scanl f z . toList++scanr :: (Dupable b) => (a %1 -> b %1 -> b) -> b %1 -> NonEmpty a %1 -> NonEmpty b+scanr f z = fromList . List.scanr f z . toList++scanl1 :: (Dupable a) => (a %1 -> a %1 -> a) -> NonEmpty a %1 -> NonEmpty a+scanl1 f (x :| xs) = fromList $ List.scanl f x xs++scanr1 :: (Dupable a) => (a %1 -> a %1 -> a) -> NonEmpty a %1 -> NonEmpty a+scanr1 f (x :| xs) = fromList $ List.scanr1 f (x : xs)++transpose :: NonEmpty (NonEmpty a) %1 -> NonEmpty (NonEmpty a)+transpose = Unsafe.toLinear NonLinear.transpose++singleton :: a %1 -> NonEmpty a+singleton = (:| [])++infixr 5 <|++(<|) :: a %1 -> NonEmpty a %1 -> NonEmpty a+a <| bs = a :| toList bs++cons :: a %1 -> NonEmpty a %1 -> NonEmpty a+cons = (<|)++uncons :: NonEmpty a %1 -> (a, Maybe (NonEmpty a))+uncons (x :| xs) = (x, nonEmpty xs)++unfoldr :: (a %1 -> (b, Maybe a)) -> a %1 -> NonEmpty b+unfoldr f a = case f a of+  (b, mc) -> b :| maybe [] go mc+  where+    go c = case f c of+      (d, me) -> d : maybe [] go me++append :: NonEmpty a %1 -> NonEmpty a %1 -> NonEmpty a+append = (<>)++appendList :: NonEmpty a %1 -> [a] %1 -> NonEmpty a+appendList (x :| xs) ys = x :| (xs <> ys)++prependList :: [a] %1 -> NonEmpty a %1 -> NonEmpty a+prependList ls ne = case ls of+  [] -> ne+  (y : ys) -> y :| (ys <> toList ne)++-- | __NOTE__: This does not short-circuit and always traverses the+-- entire list to consume the rest of the elements.+take :: (Consumable a) => Int -> NonEmpty a %1 -> [a]+take n = List.take n . toList++drop :: (Consumable a) => Int -> NonEmpty a %1 -> [a]+drop n = List.drop n . toList++splitAt :: (Consumable a) => Int -> NonEmpty a %1 -> ([a], [a])+splitAt n = List.splitAt n . toList++-- | __NOTE__: This does not short-circuit and always traverses the+-- entire list to consume the rest of the elements.+takeWhile :: (Dupable a) => (a %1 -> Bool) -> NonEmpty a %1 -> [a]+takeWhile p = List.takeWhile p . toList++dropWhile :: (Dupable a) => (a %1 -> Bool) -> NonEmpty a %1 -> [a]+dropWhile p = List.dropWhile p . toList++span :: (Dupable a) => (a %1 -> Bool) -> NonEmpty a %1 -> ([a], [a])+span p = List.span p . toList++break :: (Dupable a) => (a %1 -> Bool) -> NonEmpty a %1 -> ([a], [a])+break p = span (not . p)++filter :: (Dupable a) => (a %1 -> Bool) -> NonEmpty a %1 -> [a]+filter p = List.filter p . toList++partition :: (Dupable a) => (a %1 -> Bool) -> NonEmpty a %1 -> ([a], [a])+partition p = List.partition p . toList++-- | Return the length of the given list alongside with the list itself.+length :: NonEmpty a %1 -> (Ur Int, NonEmpty a)+length = Unsafe.toLinear $ \xs ->+  (Ur (NonLinear.length xs), xs)++fromList :: (HasCallStack) => [a] %1 -> (NonEmpty a)+fromList (x : xs) = x :| xs+fromList [] = Prelude.error "NonEmpty.Linear.fromList: empty list"++toList :: NonEmpty a %1 -> [a]+toList (x :| xs) = x : xs++nonEmpty :: [a] %1 -> Maybe (NonEmpty a)+nonEmpty (x : xs) = Just (x :| xs)+nonEmpty [] = Nothing++xor :: NonEmpty Bool %1 -> Bool+xor = Unsafe.toLinear NonLinear.xor++zip :: (Consumable a, Consumable b) => NonEmpty a %1 -> NonEmpty b %1 -> NonEmpty (a, b)+zip = zipWith (,)++zipWith :: (Consumable a, Consumable b) => (a %1 -> b %1 -> c) -> NonEmpty a %1 -> NonEmpty b %1 -> NonEmpty c+zipWith f (a :| as) (b :| bs) = f a b :| List.zipWith f as bs++-- | Same as 'zipWith', but returns the leftovers instead of consuming them.+-- Because the leftovers are returned at toplevel, @zipWith'@ is pretty strict:+-- forcing the second cons cell of the returned list forces all the recursive+-- calls.+zipWith' :: (a %1 -> b %1 -> c) -> NonEmpty a %1 -> NonEmpty b %1 -> (NonEmpty c, Maybe (Either (NonEmpty a) (NonEmpty b)))+zipWith' f (a :| as) (b :| bs) =+  case List.zipWith' f as bs of+    (cs, may) -> (f a b :| cs, may)++-- | Same as 'zip', but returns the leftovers instead of consuming them.+zip' :: NonEmpty a %1 -> NonEmpty b %1 -> (NonEmpty (a, b), Maybe (Either (NonEmpty a) (NonEmpty b)))+zip' = zipWith' (,)++unzip :: NonEmpty (a, b) %1 -> (NonEmpty a, NonEmpty b)+unzip ((a, b) :| asbs) =+  List.unzip asbs & \(as, bs) ->+    (a :| as, b :| bs)++unzip3 :: NonEmpty (a, b, c) %1 -> (NonEmpty a, NonEmpty b, NonEmpty c)+unzip3 ((a, b, c) :| abs) =+  List.unzip3 abs & \(as, bs, cs) ->+    (a :| as, b :| bs, c :| cs)
src/Data/Monoid/Linear/Internal/Semigroup.hs view
@@ -11,6 +11,7 @@ module Data.Monoid.Linear.Internal.Semigroup   ( -- * Semigroup     Semigroup (..),+    sconcat,      -- * Endo     Endo (..),@@ -34,6 +35,7 @@ import Data.Functor.Const (Const (..)) import Data.Functor.Identity (Identity (..)) import qualified Data.Functor.Product as Functor+import Data.List.NonEmpty (NonEmpty (..)) import qualified Data.Monoid as Monoid import Data.Ord (Down (..)) import Data.Proxy (Proxy (..))@@ -64,6 +66,13 @@ class Semigroup a where   (<>) :: a %1 -> a %1 -> a   infixr 6 <> -- same fixity as base.<>++sconcat :: (Semigroup a) => NonEmpty a %1 -> a+sconcat (x :| xs :: NonEmpty a) = go x xs+  where+    go :: a %1 -> [a] %1 -> a+    go acc [] = acc+    go acc (x' : xs') = go (acc <> x') xs'  -- | An @'Endo' a@ is just a linear function of type @a %1-> a@. -- This has a classic monoid definition with 'id' and '(.)'.
src/Data/Ord/Linear/Internal/Eq.hs view
@@ -13,6 +13,7 @@  import Data.Bool.Linear import Data.Int (Int16, Int32, Int64, Int8)+import Data.List.NonEmpty (NonEmpty (..)) import Data.Unrestricted.Linear import Data.Word (Word16, Word32, Word64, Word8) import Prelude.Linear.Internal@@ -46,6 +47,9 @@   [] == [] = True   (x : xs) == (y : ys) = x == y && xs == ys   xs == ys = (xs, ys) `lseq` False++instance (Consumable a, Eq a) => Eq (NonEmpty a) where+  (x :| xs) == (y :| ys) = x == y && xs == ys  instance (Consumable a, Eq a) => Eq (Prelude.Maybe a) where   Prelude.Nothing == Prelude.Nothing = True
src/Data/Ord/Linear/Internal/Ord.hs view
@@ -15,6 +15,7 @@  import Data.Bool.Linear (Bool (..), not) import Data.Int (Int16, Int32, Int64, Int8)+import Data.List.NonEmpty (NonEmpty (..)) import Data.Monoid.Linear import Data.Ord (Ordering (..)) import Data.Ord.Linear.Internal.Eq@@ -118,6 +119,10 @@     case compare x y of       EQ -> compare xs ys       res -> (xs, ys) `lseq` res++instance (Consumable a, Ord a) => Ord (NonEmpty a) where+  compare (x :| xs) (y :| ys) =+    compare x y <> compare xs ys  instance (Ord a, Ord b) => Ord (a, b) where   (a, b) `compare` (a', b') =
src/Data/Set/Mutable/Linear/Internal.hs view
@@ -1,10 +1,13 @@ {-# LANGUAGE BangPatterns #-} {-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE LinearTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StrictData #-} {-# LANGUAGE TupleSections #-}+{-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE NoImplicitPrelude #-} {-# OPTIONS_GHC -Wno-name-shadowing #-} {-# OPTIONS_HADDOCK hide #-}@@ -14,7 +17,9 @@ import qualified Data.HashMap.Mutable.Linear as Linear import Data.Monoid.Linear import Data.Unrestricted.Linear+import GHC.TypeLits (ErrorMessage (..)) import qualified Prelude.Linear as Linear hiding (insert)+import Prelude.Linear.Unsatisfiable (Unsatisfiable, unsatisfiable) import Prelude (Bool, Int) import qualified Prelude @@ -70,8 +75,11 @@ -- # Typeclass Instances ------------------------------------------------------------------------------- -instance Prelude.Semigroup (Set a) where-  (<>) = Prelude.error "Prelude.(<>): invariant violation, unrestricted Set"+instance+  (Unsatisfiable ('Text "Using Prelude's Semigroup methods on a Data.Set.Mutable.Linear is vacuous as there can't be an unrestricted such Set")) =>+  Prelude.Semigroup (Set a)+  where+  (<>) = unsatisfiable  instance (Keyed a) => Semigroup (Set a) where   (<>) = union
src/Data/Unrestricted/Linear/Internal/Instances.hs view
@@ -21,10 +21,13 @@ -- other classes (for cleanness) in this module to avoid this dependence. module Data.Unrestricted.Linear.Internal.Instances where +import Data.ByteString (ByteString)+import Data.ByteString.Short (ShortByteString) import qualified Data.Functor.Linear.Internal.Applicative as Data import qualified Data.Functor.Linear.Internal.Functor as Data import Data.Monoid.Linear import Data.Replicator.Linear.Internal.Instances ()+import qualified Data.Text import Data.Unrestricted.Linear.Internal.Consumable import Data.Unrestricted.Linear.Internal.Dupable import Data.Unrestricted.Linear.Internal.Movable@@ -189,6 +192,27 @@     V       . Unsafe.toLinear (Vector.fromListN (V.theLength @n))       Data.<$> dupR (Unsafe.toLinear Vector.toList xs)++instance Movable ByteString where+  move = Unsafe.toLinear $ \s -> s `seq` Ur s++deriving via (AsMovable ByteString) instance Consumable ByteString++deriving via (AsMovable ByteString) instance Dupable ByteString++instance Movable ShortByteString where+  move = Unsafe.toLinear $ \s -> s `seq` Ur s++deriving via (AsMovable ShortByteString) instance Consumable ShortByteString++deriving via (AsMovable ShortByteString) instance Dupable ShortByteString++instance Movable Data.Text.Text where+  move = Unsafe.toLinear $ \s -> s `seq` Ur s++deriving via (AsMovable Data.Text.Text) instance Consumable Data.Text.Text++deriving via (AsMovable Data.Text.Text) instance Dupable Data.Text.Text  -- Some stock instances 
src/Streaming/Linear/Internal/Consume.hs view
@@ -62,6 +62,7 @@ where  import qualified Control.Functor.Linear as Control+import Control.Monad.IO.Class.Linear (liftSystemIO) import qualified Data.Bool.Linear as Linear import Data.Functor.Identity import Data.Text (Text)@@ -116,7 +117,7 @@         Return r -> Control.return r         Effect ms -> ms Control.>>= stdoutLn'         Step (str :> stream) -> Control.do-          fromSystemIO $ Text.putStrLn str+          liftSystemIO $ Text.putStrLn str           stdoutLn' stream {-# INLINEABLE stdoutLn' #-} 
src/Streaming/Linear/Internal/Produce.hs view
@@ -45,6 +45,7 @@ where  import qualified Control.Functor.Linear as Control+import Control.Monad.IO.Class.Linear (liftSystemIOU) import Data.Text (Text) import qualified Data.Text as Text import Data.Unrestricted.Linear@@ -344,7 +345,7 @@   where     getALine :: () %1 -> IO (Either (Of Text ()) ())     getALine () = Control.do-      Ur line <- fromSystemIOU System.getLine+      Ur line <- liftSystemIOU System.getLine       Control.return $ Left (Text.pack line :> ())  -- | An affine stream of reading lines, crashing on failed parse.@@ -353,7 +354,7 @@   where     readALine :: (Read a) => () %1 -> IO (Either (Of a ()) ())     readALine () = Control.do-      Ur line <- fromSystemIOU System.getLine+      Ur line <- liftSystemIOU System.getLine       Control.return $ Left (Prelude.read line :> ())  -- | An affine stream iterating an initial state forever.
src/System/IO/Resource/Linear.hs view
@@ -32,6 +32,11 @@     RIO,     run, +    -- * Interfacing with IO+    fromIO,+    fromSystemIO,+    fromSystemIOU,+     -- * Using Resource Handles     -- $monad     -- $files
src/System/IO/Resource/Linear/Internal.hs view
@@ -88,10 +88,24 @@       result <- action'       Control.return $ move result --- | Should not be applied to a function that acquires or releases resources.-unsafeFromSystemIO :: System.IO a %1 -> RIO a-unsafeFromSystemIO action = RIO (\_ -> Linear.fromSystemIO action)+-- | Coerces a linear IO action into a 'RIO' action.+fromIO :: Linear.IO a %1 -> RIO a+fromIO action = RIO (\_ -> action) +-- | Coerces a standard IO action into a 'RIO' action.+-- Note that the value @a@ must be used linearly in the 'RIO' monad.+fromSystemIO :: System.IO a %1 -> RIO a+fromSystemIO action =+  -- Should not be applied to a function that acquires or releases resources.+  fromIO (Linear.fromSystemIO action)++-- | Coerces a standard IO action into a 'RIO' action, allowing you to use+-- the result of type @a@ in a non-linear manner by wrapping it inside+-- 'Ur'.+fromSystemIOU :: System.IO a -> RIO (Ur a)+fromSystemIOU action =+  fromIO (Linear.fromSystemIOU action)+ -- monad  instance Control.Functor RIO where@@ -235,7 +249,7 @@   (a -> System.IO b) ->   (Resource a %1 -> RIO (Ur b, Resource a)) unsafeFromSystemIOResource action (UnsafeResource key resource) =-  unsafeFromSystemIO+  fromSystemIO     ( do         c <- action resource         Prelude.return (Ur c, UnsafeResource key resource)
test/Test/Data/List.hs view
@@ -1,9 +1,11 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE NoImplicitPrelude #-}+{-# OPTIONS_GHC -Wno-x-partial #-}  module Test.Data.List (listTests) where  import qualified Data.List.Linear as List+import qualified Data.Num.Linear as Num import Hedgehog import qualified Hedgehog.Gen as Gen import qualified Hedgehog.Range as Range@@ -17,7 +19,9 @@   testGroup     "List tests"     [ testPropertyNamed "take n ++ drop n = id" "take_drop" take_drop,-      testPropertyNamed "length . take n = const n" "take_length" take_length+      testPropertyNamed "length . take n = const n" "take_length" take_length,+      testPropertyNamed "zipWith is lazy" "zipWith_lazy" zipWith_lazy,+      testPropertyNamed "zipWith3 is lazy" "zipWith3_lazy" zipWith3_lazy     ]  take_drop :: Property@@ -41,3 +45,22 @@     False -> do       annotate "Prelude.length xs < n"       Prelude.length (List.take n xs) === Prelude.length xs++zipWith_lazy :: Property+zipWith_lazy = property $ do+  lgth <- forAll $ Gen.word (Range.linear 0 50)+  _ <- eval $ Prelude.head (xs lgth)+  Prelude.return ()+  where+    xs :: Word -> [Word]+    xs lgth = List.zipWith (Num.+) (0 : error "bottom") [0 .. lgth]++zipWith3_lazy :: Property+zipWith3_lazy = property $ do+  lgth1 <- forAll $ Gen.word (Range.linear 0 50)+  lgth2 <- forAll $ Gen.word (Range.linear 0 50)+  _ <- eval $ Prelude.head (xs lgth1 lgth2)+  Prelude.return ()+  where+    xs :: Word -> Word -> [Word]+    xs lgth1 lgth2 = List.zipWith3 (\x y z -> x Num.+ y Num.+ z) (0 : error "bottom") [0 .. lgth1] [0 .. lgth2]