Expose the StableName constructor
authorDavid Feuer <david.feuer@gmail.com>
Tue, 21 Aug 2018 00:08:14 +0000 (20:08 -0400)
committerBen Gamari <ben@smart-cactus.org>
Thu, 23 Aug 2018 22:50:28 +0000 (18:50 -0400)
* Move the definition of `StableName` from `System.Mem.StableName`
  to a new `GHC.StableName` module.

* Expose the `StableName` data constructor from `GHC.StableName`.
  Once we have `UnliftedArray#`, this will enable `StableName`s to
  be stored in `UnliftedArray`s (from `primitive`) without unsafe
  coercions.

Reviewers: hvr, bgamari, andrewthad, osa1

Reviewed By: osa1

Subscribers: osa1, rwbarton, carter

GHC Trac Issues: #15535

Differential Revision: https://phabricator.haskell.org/D5078

(cherry picked from commit 9c4e6c6b1affd410604f8f76ecf56abfcc5cccb6)

libraries/base/GHC/StableName.hs [new file with mode: 0644]
libraries/base/System/Mem/StableName.hs
libraries/base/base.cabal

diff --git a/libraries/base/GHC/StableName.hs b/libraries/base/GHC/StableName.hs
new file mode 100644 (file)
index 0000000..7369f41
--- /dev/null
@@ -0,0 +1,106 @@
+{-# LANGUAGE Trustworthy #-}
+{-# LANGUAGE StandaloneDeriving #-}
+{-# LANGUAGE MagicHash #-}
+{-# LANGUAGE UnboxedTuples #-}
+
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  System.Mem.StableName
+-- Copyright   :  (c) The University of Glasgow 2001
+-- License     :  BSD-style (see the file libraries/base/LICENSE)
+--
+-- Maintainer  :  libraries@haskell.org
+-- Stability   :  experimental
+-- Portability :  non-portable
+--
+-- Stable names are a way of performing fast (O(1)), not-quite-exact
+-- comparison between objects.
+--
+-- Stable names solve the following problem: suppose you want to build
+-- a hash table with Haskell objects as keys, but you want to use
+-- pointer equality for comparison; maybe because the keys are large
+-- and hashing would be slow, or perhaps because the keys are infinite
+-- in size.  We can\'t build a hash table using the address of the
+-- object as the key, because objects get moved around by the garbage
+-- collector, meaning a re-hash would be necessary after every garbage
+-- collection.
+--
+-------------------------------------------------------------------------------
+
+module GHC.StableName (
+  -- * Stable Names
+  StableName (..),
+  makeStableName,
+  hashStableName,
+  eqStableName
+  ) where
+
+import GHC.IO           ( IO(..) )
+import GHC.Base         ( Int(..), StableName#, makeStableName#
+                        , eqStableName#, stableNameToInt# )
+
+-----------------------------------------------------------------------------
+-- Stable Names
+
+{-|
+  An abstract name for an object, that supports equality and hashing.
+
+  Stable names have the following property:
+
+  * If @sn1 :: StableName@ and @sn2 :: StableName@ and @sn1 == sn2@
+   then @sn1@ and @sn2@ were created by calls to @makeStableName@ on
+   the same object.
+
+  The reverse is not necessarily true: if two stable names are not
+  equal, then the objects they name may still be equal.  Note in particular
+  that `makeStableName` may return a different `StableName` after an
+  object is evaluated.
+
+  Stable Names are similar to Stable Pointers ("Foreign.StablePtr"),
+  but differ in the following ways:
+
+  * There is no @freeStableName@ operation, unlike "Foreign.StablePtr"s.
+    Stable names are reclaimed by the runtime system when they are no
+    longer needed.
+
+  * There is no @deRefStableName@ operation.  You can\'t get back from
+    a stable name to the original Haskell object.  The reason for
+    this is that the existence of a stable name for an object does not
+    guarantee the existence of the object itself; it can still be garbage
+    collected.
+-}
+
+data StableName a = StableName (StableName# a)
+
+-- | Makes a 'StableName' for an arbitrary object.  The object passed as
+-- the first argument is not evaluated by 'makeStableName'.
+makeStableName  :: a -> IO (StableName a)
+makeStableName a = IO $ \ s ->
+    case makeStableName# a s of (# s', sn #) -> (# s', StableName sn #)
+
+-- | Convert a 'StableName' to an 'Int'.  The 'Int' returned is not
+-- necessarily unique; several 'StableName's may map to the same 'Int'
+-- (in practice however, the chances of this are small, so the result
+-- of 'hashStableName' makes a good hash key).
+hashStableName :: StableName a -> Int
+hashStableName (StableName sn) = I# (stableNameToInt# sn)
+
+-- | @since 2.01
+instance Eq (StableName a) where
+    (StableName sn1) == (StableName sn2) =
+       case eqStableName# sn1 sn2 of
+         0# -> False
+         _  -> True
+
+-- | Equality on 'StableName' that does not require that the types of
+-- the arguments match.
+--
+-- @since 4.7.0.0
+eqStableName :: StableName a -> StableName b -> Bool
+eqStableName (StableName sn1) (StableName sn2) =
+       case eqStableName# sn1 sn2 of
+         0# -> False
+         _  -> True
+  -- Requested by Emil Axelsson on glasgow-haskell-users, who wants to
+  -- use it for implementing observable sharing.
+
index dcd5273..064d928 100644 (file)
@@ -1,7 +1,4 @@
-{-# LANGUAGE Trustworthy #-}
-{-# LANGUAGE StandaloneDeriving #-}
-{-# LANGUAGE MagicHash #-}
-{-# LANGUAGE UnboxedTuples #-}
+{-# LANGUAGE Safe #-}
 
 -----------------------------------------------------------------------------
 -- |
@@ -35,72 +32,4 @@ module System.Mem.StableName (
   eqStableName
   ) where
 
-import GHC.IO           ( IO(..) )
-import GHC.Base         ( Int(..), StableName#, makeStableName#
-                        , eqStableName#, stableNameToInt# )
-
------------------------------------------------------------------------------
--- Stable Names
-
-{-|
-  An abstract name for an object, that supports equality and hashing.
-
-  Stable names have the following property:
-
-  * If @sn1 :: StableName@ and @sn2 :: StableName@ and @sn1 == sn2@
-   then @sn1@ and @sn2@ were created by calls to @makeStableName@ on
-   the same object.
-
-  The reverse is not necessarily true: if two stable names are not
-  equal, then the objects they name may still be equal.  Note in particular
-  that `makeStableName` may return a different `StableName` after an
-  object is evaluated.
-
-  Stable Names are similar to Stable Pointers ("Foreign.StablePtr"),
-  but differ in the following ways:
-
-  * There is no @freeStableName@ operation, unlike "Foreign.StablePtr"s.
-    Stable names are reclaimed by the runtime system when they are no
-    longer needed.
-
-  * There is no @deRefStableName@ operation.  You can\'t get back from
-    a stable name to the original Haskell object.  The reason for
-    this is that the existence of a stable name for an object does not
-    guarantee the existence of the object itself; it can still be garbage
-    collected.
--}
-
-data StableName a = StableName (StableName# a)
-
--- | Makes a 'StableName' for an arbitrary object.  The object passed as
--- the first argument is not evaluated by 'makeStableName'.
-makeStableName  :: a -> IO (StableName a)
-makeStableName a = IO $ \ s ->
-    case makeStableName# a s of (# s', sn #) -> (# s', StableName sn #)
-
--- | Convert a 'StableName' to an 'Int'.  The 'Int' returned is not
--- necessarily unique; several 'StableName's may map to the same 'Int'
--- (in practice however, the chances of this are small, so the result
--- of 'hashStableName' makes a good hash key).
-hashStableName :: StableName a -> Int
-hashStableName (StableName sn) = I# (stableNameToInt# sn)
-
--- | @since 2.01
-instance Eq (StableName a) where
-    (StableName sn1) == (StableName sn2) =
-       case eqStableName# sn1 sn2 of
-         0# -> False
-         _  -> True
-
--- | Equality on 'StableName' that does not require that the types of
--- the arguments match.
---
--- @since 4.7.0.0
-eqStableName :: StableName a -> StableName b -> Bool
-eqStableName (StableName sn1) (StableName sn2) =
-       case eqStableName# sn1 sn2 of
-         0# -> False
-         _  -> True
-  -- Requested by Emil Axelsson on glasgow-haskell-users, who wants to
-  -- use it for implementing observable sharing.
-
+import GHC.StableName
index dbeec33..f02ff08 100644 (file)
@@ -278,6 +278,7 @@ Library
         GHC.STRef
         GHC.Show
         GHC.Stable
+        GHC.StableName
         GHC.Stack
         GHC.Stack.CCS
         GHC.Stack.Types