packages feed

rt (empty) → 0.1.0.0

raw patch · 7 files changed

+208/−0 lines, 7 filesdep +base

Dependencies added: base

Files

+ CHANGELOG.md view
@@ -0,0 +1,5 @@+# Revision history for rt++## 0.1.0.0 -- 2024-04-08++* First version. Released on an unsuspecting world.
+ LICENSE view
@@ -0,0 +1,28 @@+BSD 3-Clause License++Copyright (c) 2024, Jamie Willis++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++1. Redistributions of source code must retain the above copyright notice, this+   list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright notice,+   this list of conditions and the following disclaimer in the documentation+   and/or other materials provided with the distribution.++3. Neither the name of the copyright holder nor the names of its+   contributors may be used to endorse or promote products derived from+   this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ rt.cabal view
@@ -0,0 +1,79 @@+cabal-version:      3.0+-- The cabal-version field refers to the version of the .cabal specification,+-- and can be different from the cabal-install (the tool) version and the+-- Cabal (the library) version you are using. As such, the Cabal (the library)+-- version used must be equal or greater than the version stated in this field.+-- Starting from the specification version 2.2, the cabal-version field must be+-- the first thing in the cabal file.++-- Initial package description 'rt' generated by+-- 'cabal init'. For further documentation, see:+--   http://haskell.org/cabal/users-guide/+--+-- The name of the package.+name:               rt++-- The package version.+-- See the Haskell package versioning policy (PVP) for standards+-- guiding when and how versions should be incremented.+-- https://pvp.haskell.org+-- PVP summary:     +-+------- breaking API changes+--                  | | +----- non-breaking API additions+--                  | | | +--- code changes with no API change+version:            0.1.0.0++-- A short (one-line) description of the package.+synopsis:           A more fine-grained version of state threads (ST)++-- A longer description of the package.+description:        Introduces the RT monad, which can be used to have more fine-grained STRefs without an extra parameter+                    in the monad.++-- URL for the project homepage or repository.+homepage:           https://github.com/j-mie6/reference-threads++-- The license under which the package is released.+license:            BSD-3-Clause++-- The file containing the license text.+license-file:       LICENSE++-- The package author(s).+author:             Jamie Willis++-- An email address to which users can send suggestions, bug reports, and patches.+maintainer:         j.willis19@imperial.ac.uk++copyright: (c) 2024-present Jamie Willis+category:           Control+build-type:         Simple++-- Extra doc files to be distributed with the package, such as a CHANGELOG or a README.+extra-doc-files:    CHANGELOG.md++source-repository head+    type:     git+    location: git://github.com/j-mie6/reference-threads.git++common warnings+    ghc-options: -Wall++library+    -- Import common warning flags.+    import:           warnings++    -- Modules exported by the library.+    exposed-modules:  Control.Monad.RT+                      Control.Monad.RT.Unsafe+                      Data.Ref+                      Data.Ref.Impl+                      --Data.Array.RT++    -- Other library packages from which modules are imported.+    build-depends:    base >=4.14 && < 5++    -- Directories containing source files.+    hs-source-dirs:   src++    -- Base language which the package is written in.+    default-language: Haskell2010
+ src/Control/Monad/RT.hs view
@@ -0,0 +1,17 @@+{-# LANGUAGE Trustworthy #-}+{-# LANGUAGE MagicHash, UnboxedTuples #-}+module Control.Monad.RT (RT, module Control.Monad.RT) where++import Control.Monad.RT.Unsafe++import GHC.Base (runRW#)+import GHC.IO (IO(IO))+import Data.Coerce (coerce)++{-# INLINE runRT #-}+runRT :: RT a -> a+runRT (RT mx) = case runRW# mx of (# _, x #) -> x++{-# INLINE rtToIO #-}+rtToIO :: RT a -> IO a+rtToIO = coerce
+ src/Control/Monad/RT/Unsafe.hs view
@@ -0,0 +1,15 @@+{-# LANGUAGE Unsafe #-}+{-# LANGUAGE UnboxedTuples, MagicHash, DerivingVia, DataKinds #-}+module Control.Monad.RT.Unsafe (module Control.Monad.RT.Unsafe) where++import GHC.Base (State#, RealWorld)+import GHC.IO (IO(IO))+import Data.Coerce (coerce)++-- do the instances by hand?+newtype RT a = RT (State# RealWorld -> (# State# RealWorld, a #))+  deriving (Functor, Applicative, Monad) via IO++{-# INLINE unsafeIOToRT #-}+unsafeIOToRT :: IO a -> RT a+unsafeIOToRT = coerce
+ src/Data/Ref.hs view
@@ -0,0 +1,42 @@+{-# LANGUAGE Trustworthy #-}+{-# LANGUAGE MagicHash, UnboxedTuples, RankNTypes, TypeOperators #-}+module Data.Ref (Ref, module Data.Ref) where++import Control.Monad.RT.Unsafe (RT(RT))+import Data.Ref.Impl (Ref(Ref))++import GHC.Base (newMutVar#, readMutVar#, writeMutVar#)++import GHC.IORef (IORef(IORef))+import GHC.STRef (STRef(STRef))++import Data.Type.Equality ((:~:)(Refl))+import Unsafe.Coerce (unsafeCoerce)+++{-# INLINABLE newRef #-}+newRef :: a -> (forall r. Ref r a -> RT b) -> RT b+newRef x k = RT $ \s# ->+  case newMutVar# x s# of+    (# s'#, ref# #) -> let RT k' = k (Ref ref#) in k' s'#++{-# INLINE readRef #-}+readRef :: Ref r a -> RT a+readRef (Ref ref#) = RT $ \s# -> readMutVar# ref# s#++{-# INLINABLE writeRef #-}+writeRef :: Ref r a -> a -> RT ()+writeRef (Ref ref#) x = RT $ \s# ->+  case writeMutVar# ref# x s# of+    s'# -> (# s'#, () #)++-- unsafeFromIORef?+{-# INLINE fromIORef #-}+fromIORef :: IORef a -> Ref r a+fromIORef (IORef (STRef ref#)) = Ref ref#++-- returns a proof that if two references are equal, they must have the same lifetime+lifetimeEqual :: Ref r1 a -> Ref r2 a -> Maybe (r1 :~: r2)+lifetimeEqual (Ref ref1#) ref2+  | Ref ref1# == ref2 = Just (unsafeCoerce Refl)+  | otherwise         = Nothing
+ src/Data/Ref/Impl.hs view
@@ -0,0 +1,22 @@+{-# LANGUAGE DataKinds, MagicHash, RoleAnnotations #-}+module Data.Ref.Impl (module Data.Ref.Impl) where++import GHC.Base (MutVar#, RealWorld, sameMutVar#, isTrue#)++{-+The `r` parameter is deliberately nominal here, which prevents the use of+coerce to "safely" escape the lifetime of a reference:++> escape :: a -> RT (Ref r a)+> escape x = newRef x (return . coerce)++Would compile if the annotation was left as phantom (which is the inferred).+This is clearly not something we want to allow, so nominal it is.+-}+type role Ref nominal representational+-- Don't even expose the constructor, then it's pretty much safe?+data Ref r a = Ref (MutVar# RealWorld a)++-- It's nice that two references must clearly have the same lifetime to be equal+instance Eq (Ref r a) where+  Ref ref1# == Ref ref2# = isTrue# (sameMutVar# ref1# ref2#)