summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHerbertValerioRiedel <>2019-09-10 18:57:00 (GMT)
committerhdiff <hdiff@hdiff.luite.com>2019-09-10 18:57:00 (GMT)
commita7dec86c4e2acfd447f95cb0c77b394b3a2609fe (patch)
tree3776e67bb85d26c0af8e1f32442575943d9ceda6
parent105e146708d4215c94ba8b3dd663fe5fc0b44080 (diff)
version 0.2.2.0HEAD0.2.2.0master
-rwxr-xr-xCHANGES.md5
-rw-r--r--Control/Newtype.hs39
-rw-r--r--Setup.hs5
-rw-r--r--newtype.cabal4
4 files changed, 51 insertions, 2 deletions
diff --git a/CHANGES.md b/CHANGES.md
index e336c84..492415b 100755
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,5 +1,10 @@
See also https://pvp.haskell.org/faq
+## 0.2.2.0 *(minor)*
+
+ - Provide safe `Coercible`-based default-methods for `pack`/`unpack`
+ ([#1](https://github.com/haskell-hvr/newtype/pull/1))
+
## 0.2.1.0 *(minor)*
- Added `Newtype` instances for
diff --git a/Control/Newtype.hs b/Control/Newtype.hs
index f5ca2d5..5de2637 100644
--- a/Control/Newtype.hs
+++ b/Control/Newtype.hs
@@ -3,6 +3,9 @@
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
+#if __GLASGOW_HASKELL__ >= 704
+{-# LANGUAGE DefaultSignatures #-}
+#endif
{-# OPTIONS_GHC -fno-warn-unused-imports #-}
@@ -48,15 +51,51 @@ import Data.Ord
#if !MIN_VERSION_base(4,7,0)
-- necessary evil for 'Newtype Fixed'
import Unsafe.Coerce (unsafeCoerce)
+#else
+import Data.Coerce
#endif
-- | Given a @newtype@ @n@, we will always have the same unwrapped type @o@, meaning we can represent this with a fundep @n -> o@.
--
-- Any instance of this class just needs to let 'pack' equal to the newtype's constructor, and let 'unpack' destruct the @newtype@ with pattern matching.
+--
+-- Starting with @newtype-0.2.2.0@, default method implementations are provided using "Data.Coerce" for GHC 7.8 (i.e. @base-4.7.0.0@) and later, i.e.:
+--
+-- @
+-- 'pack' = 'coerce'
+-- 'unpack' = 'coerce'
+-- @
+--
+-- When omitting the method definitions with GHC 7.4 and 7.6 a compile error will be triggered.
+--
+-- Consequently, if your code relies on these default methods make sure to state
+--
+-- > build-depends: newtype ^>= 0.2.2.0
+--
+-- In your @.cabal@ package description.
class Newtype n o | n -> o where
pack :: o -> n
+
unpack :: n -> o
+#if __GLASGOW_HASKELL__ >= 704
+ default pack :: Coercible o n => o -> n
+ pack = coerce
+
+ default unpack :: Coercible n o => n -> o
+ unpack = coerce
+#endif
+
+#if __GLASGOW_HASKELL__ >= 704 && !MIN_VERSION_base(4,7,0)
+-- Hack: We define a dummy 'Coercible' class to force a
+-- missing-instance compile error when methods are not explicitly
+-- defined
+class Coercible o n
+
+coerce :: a -> b
+coerce = undefined
+#endif
+
{- TODO: for newtype-0.3
This would be nice, but it breaks in odd ways with GHC < 7.
diff --git a/Setup.hs b/Setup.hs
index 9a994af..28d0f3a 100644
--- a/Setup.hs
+++ b/Setup.hs
@@ -1,2 +1,7 @@
+
import Distribution.Simple
+
+
+
+
main = defaultMain
diff --git a/newtype.cabal b/newtype.cabal
index 489228e..44c338d 100644
--- a/newtype.cabal
+++ b/newtype.cabal
@@ -1,7 +1,7 @@
cabal-version: 1.12
build-type: Simple
name: newtype
-version: 0.2.1.0
+version: 0.2.2.0
license: BSD3
license-file: LICENSE
@@ -22,7 +22,7 @@ source-repository head
library
exposed-modules: Control.Newtype
- build-depends: base >= 4.3 && < 4.14
+ build-depends: base >= 4.5 && < 4.14
if !impl(ghc >= 8.0)
build-depends: transformers >= 0.2.2.0 && < 0.6