diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,11 @@
 # Changelog for unboxing-vector
 
+## Version 0.1.1.0 (2019-07-01)
+
+- Support older GHC versions.
+- Add `Enum` and `EnumRep` wrappers.
+- Add `Unboxable` instance for `Ordering`.
+
 ## Version 0.1.0.0 (2019-06-17)
 
 Initial release with
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,5 +1,7 @@
-# unboxing-vector
+# unboxing-vector: A newtype-friendly variant of unboxed vectors
 
+[![Build Status](https://travis-ci.org/minoki/unboxing-vector.svg?branch=master)](https://travis-ci.org/minoki/unboxing-vector)
+
 This package provides newtype-friendly wrappers for `Data.Vector.Unboxed` in [`vector` package](http://hackage.haskell.org/package/vector).
 
 ## Description
@@ -7,48 +9,69 @@
 Suppose you define a newtype for `Int` and want to store them in an unboxed vector.
 
 ```haskell
+import qualified Data.Vector.Unboxed as Unboxed
+
 newtype Foo = Foo Int
 
-generate 10 (\i -> Foo i) :: Data.Vector.Unboxed.Vector Foo
+vec :: Unboxed.Vector Foo
+vec = Unboxed.generate 10 (\i -> Foo i)
 ```
 
-With plain `Data.Vector.Unboxed`, you either write two dozen of lines of code to get it work (the exact code is [here](https://github.com/minoki/unboxing-vector/blob/3a152014b9660ef1e2885d6b9c66423064223f63/test/Foo.hs#L36-L63)), or resort to Template Haskell ([`vector-th-unbox` package](http://hackage.haskell.org/package/vector-th-unbox)) to generate it.
+With classic `Data.Vector.Unboxed`, you either write _two dozen of lines_ of code to get it work (the exact code is [here](https://github.com/minoki/unboxing-vector/blob/3a152014b9660ef1e2885d6b9c66423064223f63/test/Foo.hs#L36-L63)), or resort to Template Haskell ([`vector-th-unbox` package](http://hackage.haskell.org/package/vector-th-unbox)) to generate it.
 
-But with `Data.Vector.Unboxing`, the code you write is just two lines:
+Now you have the third option, namely `Data.Vector.Unboxing`.
+With `Data.Vector.Unboxing`, the amount of code you write is just _two lines_:
 
 ```haskell
-instance Data.Vector.Unboxing.Unboxable Foo where
+import qualified Data.Vector.Unboxing as Unboxing
+
+instance Unboxing.Unboxable Foo where
   type Rep Foo = Int
 
-generate 10 (\i -> Foo i) :: Data.Vector.Unboxing.Vector Foo
+vec :: Unboxing.Vector Foo
+vec = Unboxing.generate 10 (\i -> Foo i)
 ```
 
 ...and if you want to be even more concise, you can derive `Unboxable` instance with `GeneralizedNewtypeDeriving`.
 
 Note that the vector type provided by this package (`Data.Vector.Unboxing.Vector`) is *different* from `Data.Vector.Unboxed.Vector`.
+If you need to convert `Unboxing.Vector` to `Unboxed.Vector`, or vice versa, use `Unboxing.toUnboxedVector` or `Unboxing.fromUnboxedVector`.
 
-The module defining the type `Foo` does not need to export its constructor to enable use of `Vector Foo`.
+The module defining the type `Foo` does not need to export its constructor to enable use of `Unboxing.Vector Foo`.
+In that case, the users of the abstract data type cannot convert between `Unboxing.Vector Int` and `Unboxing.Vector Foo` --- the abstraction is kept!
 
 ## For non-newtypes
 
-Suppose you define a datatype isomorphic to a tuple of primitive types, like:
+Suppose you define a data type isomorphic to a tuple, like:
 
 ```haskell
 data ComplexDouble = MkComplexDouble {-# UNPACK #-} !Double {-# UNPACK #-} !Double
 ```
 
-In this example, `ComplexDouble` is isomorphic to `(Double, Double)`, but has a different representation. Thus, you cannot derive `Data.Vector.Unboxing.Unboxable` from `(Double, Double)`.
+In this example, `ComplexDouble` is isomorphic to `(Double, Double)`, but has a different representation. Thus, you cannot derive `Unboxing.Unboxable` from `(Double, Double)`.
 
 For such cases, unboxing-vector provides a feature to derive `Unboxable` using `Generic`.
+Use `Unboxing.Generics` newtype wrapper to derive it.
 
 ```haskell
 {-# LANGUAGE DeriveGeneric, DerivingVia, UndecidableInstances #-}
 
-data ComplexDouble = ..
+data ComplexDouble = MkComplexDouble {-# UNPACK #-} !Double {-# UNPACK #-} !Double
   deriving Generic
   deriving Data.Vector.Unboxing.Unboxable via Data.Vector.Unboxing.Generics ComplexDouble
 ```
 
+Unboxing via `fromEnum`/`toEnum` is also available.
+Use `Unboxing.Enum` or `Unboxing.EnumRep` to derive it.
+
+```haskell
+{-# LANGUAGE DerivingVia, UndecidableInstances #-}
+
+data Direction = North | South | East | West
+  deriving Enum
+  deriving Unboxing.Unboxable via Unboxing.EnumRep Int8 Direction
+```
+
 ## Conversion
 
 ### Conversion from/to Unboxed vector
@@ -78,3 +101,15 @@
 and :: Unboxing.Vector Bool -> Bool
 and vec = getAll $ ofold (Unboxing.coerceVector vec :: Unboxing.Vector All) -- fails because the data constructor is not in scope
 ```
+
+## Supported GHC versions
+
+The library itself is tested with GHC 8.0.2 or later.
+
+To use `GeneralizedNewtypeDeriving` on `Unboxable` class, you need GHC 8.2 or later,
+because GND for associated type families became available on that version.
+
+`DerivingVia` is avaliable since GHC 8.6.1.
+This means that, defining an `Unboxable` instance for user-defined `data` types (like `ComplexDouble` or `Direction` in this document) requires a latest GHC.
+
+If you want a way to make your `data` types on older GHCs, please [open an issue on GitHub](https://github.com/minoki/unboxing-vector/issues).
diff --git a/src/Data/Vector/Unboxing.hs b/src/Data/Vector/Unboxing.hs
--- a/src/Data/Vector/Unboxing.hs
+++ b/src/Data/Vector/Unboxing.hs
@@ -3,6 +3,8 @@
   (Vector
   ,Unboxable(Rep)
   ,Generics(..)
+  ,Enum(..)
+  ,EnumRep(..)
   -- * Accessors
   -- ** Length information
   ,length,null
@@ -83,7 +85,8 @@
   ,freeze,thaw,copy,unsafeFreeze,unsafeThaw,unsafeCopy
   ) where
 
-import Prelude (Monad,Int,Bool,Maybe,Traversable,Eq,Num,Enum,Ord,Ordering)
+import Prelude (Monad,Int,Bool,Maybe,Traversable,Eq,Num,Ord,Ordering)
+import qualified Prelude
 import qualified Data.Vector.Generic as G
 import Data.Vector.Generic (convert)
 import Data.Vector.Unboxing.Internal
@@ -266,11 +269,11 @@
 enumFromStepN = G.enumFromStepN
 {-# INLINE enumFromStepN #-}
 
-enumFromTo :: (Enum a, Unboxable a) => a -> a -> Vector a
+enumFromTo :: (Prelude.Enum a, Unboxable a) => a -> a -> Vector a
 enumFromTo = G.enumFromTo
 {-# INLINE enumFromTo #-}
 
-enumFromThenTo :: (Enum a, Unboxable a) => a -> a -> a -> Vector a
+enumFromThenTo :: (Prelude.Enum a, Unboxable a) => a -> a -> a -> Vector a
 enumFromThenTo = G.enumFromThenTo
 {-# INLINE enumFromThenTo #-}
 
diff --git a/src/Data/Vector/Unboxing/Internal.hs b/src/Data/Vector/Unboxing/Internal.hs
--- a/src/Data/Vector/Unboxing/Internal.hs
+++ b/src/Data/Vector/Unboxing/Internal.hs
@@ -6,7 +6,6 @@
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE StandaloneDeriving #-}
 {-# LANGUAGE TypeApplications #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE TypeOperators #-}
@@ -17,6 +16,8 @@
   ,Vector(UnboxingVector)
   ,MVector(UnboxingMVector)
   ,Generics(..)
+  ,Enum(..)
+  ,EnumRep(..)
   ,coerceVector
   ,liftCoercion
   ,vectorCoercion
@@ -27,6 +28,8 @@
   ,fromUnboxedMVector
   ,coercionWithUnboxedMVector
   ) where
+import Prelude hiding (Enum)
+import qualified Prelude
 import qualified Data.Vector.Generic as G
 import qualified Data.Vector.Generic.Mutable as GM
 import qualified Data.Vector.Unboxed as U
@@ -135,9 +138,9 @@
 coercionWithUnboxedMVector = Coercion
 {-# INLINE coercionWithUnboxedMVector #-}
 
------
-
+--
 -- Generics
+--
 
 -- | A newtype wrapper to be used with @DerivingVia@.
 --
@@ -148,13 +151,13 @@
 -- >   deriving Unboxable via Generics Bar
 newtype Generics a = Generics a
 
-instance (GHC.Generics.Generic a, Unboxable (Rep' (GHC.Generics.Rep a)), Unboxable' (GHC.Generics.Rep a)) => Unboxable (Generics a) where
-  type Rep (Generics a) = Rep (Rep' (GHC.Generics.Rep a))
+instance (GHC.Generics.Generic a, U.Unbox (Rep' (GHC.Generics.Rep a)), Unboxable' (GHC.Generics.Rep a)) => Unboxable (Generics a) where
+  type Rep (Generics a) = Rep' (GHC.Generics.Rep a)
   type CoercibleRep (Generics a) = a
   type IsTrivial (Generics a) = 'False
-  unboxingFrom (Generics x) = unboxingFrom (from' (GHC.Generics.from x))
+  unboxingFrom (Generics x) = from' (GHC.Generics.from x)
   {-# INLINE unboxingFrom #-}
-  unboxingTo y = Generics (GHC.Generics.to (to' (unboxingTo y)))
+  unboxingTo y = Generics (GHC.Generics.to (to' y))
   {-# INLINE unboxingTo #-}
 
 class Unboxable' f where
@@ -190,9 +193,48 @@
   from' = undefined
   to' = undefined
 
------
+--
+-- Enum
+--
 
+-- | A newtype wrapper to be used with @DerivingVia@.
+-- The value will be stored as 'Int', via `fromEnum`/`toEnum`.
+--
+-- Usage:
+--
+-- > data Direction = North | South | East | West
+-- >   deriving Enum
+-- >   deriving Data.Vector.Unboxing.Unboxable via Data.Vector.Unboxing.Enum Bar
+newtype Enum a = Enum a
+instance (Prelude.Enum a) => Unboxable (Enum a) where
+  type Rep (Enum a) = Int
+  type CoercibleRep (Enum a) = a
+  type IsTrivial (Enum a) = 'False
+  unboxingFrom (Enum x) = fromEnum x
+  {-# INLINE unboxingFrom #-}
+  unboxingTo y = Enum (toEnum y)
+  {-# INLINE unboxingTo #-}
+
+-- | A newtype wrapper to be used with @DerivingVia@.
+--
+-- Usage:
+--
+-- > data Direction = North | South | East | West
+-- >   deriving Enum
+-- >   deriving Data.Vector.Unboxing.Unboxable via Data.Vector.Unboxing.EnumRep Int8 Bar
+newtype EnumRep rep a = EnumRep a
+instance (Prelude.Enum a, Integral rep, U.Unbox rep) => Unboxable (EnumRep rep a) where
+  type Rep (EnumRep rep a) = rep
+  type CoercibleRep (EnumRep rep a) = a
+  type IsTrivial (EnumRep rep a) = 'False
+  unboxingFrom (EnumRep x) = fromIntegral (fromEnum x)
+  {-# INLINE unboxingFrom #-}
+  unboxingTo y = EnumRep (toEnum (fromIntegral y))
+  {-# INLINE unboxingTo #-}
+
+--
 -- Instances
+--
 
 instance (Unboxable a) => IsList (Vector a) where
   type Item (Vector a) = a
@@ -223,15 +265,15 @@
   {-# INLINE readPrec #-}
   {-# INLINE readListPrec #-}
 
-instance (Unboxable a) => Semigroup (Vector a) where
+instance (Unboxable a) => Data.Semigroup.Semigroup (Vector a) where
   (<>) = (G.++)
   sconcat = G.concatNE
   {-# INLINE (<>) #-}
   {-# INLINE sconcat #-}
 
-instance (Unboxable a) => Monoid (Vector a) where
+instance (Unboxable a) => Data.Monoid.Monoid (Vector a) where
   mempty = G.empty
-  mappend = (<>)
+  mappend = (Data.Semigroup.<>)
   mconcat = G.concat
   {-# INLINE mempty #-}
   {-# INLINE mappend #-}
@@ -283,9 +325,9 @@
   {-# INLINE basicUnsafeCopy #-}
   {-# INLINE elemseq #-}
 
------
-
+--
 -- Classes from mono-traversable
+--
 
 type instance Data.MonoTraversable.Element (Vector a) = a
 
@@ -432,9 +474,9 @@
   {-# INLINE indexEx #-}
   {-# INLINE unsafeIndex #-}
 
------
-
+--
 -- Unboxable instances
+--
 
 instance Unboxable Bool where   type Rep Bool = Bool
 instance Unboxable Char where   type Rep Char = Char
@@ -506,16 +548,111 @@
   {-# INLINE unboxingFrom #-}
   {-# INLINE unboxingTo #-}
 
-deriving instance Unboxable a => Unboxable (Data.Functor.Identity.Identity a)
-deriving instance Unboxable a => Unboxable (Data.Functor.Const.Const a b)
-deriving instance Unboxable a => Unboxable (Data.Semigroup.Min a)
-deriving instance Unboxable a => Unboxable (Data.Semigroup.Max a)
-deriving instance Unboxable a => Unboxable (Data.Semigroup.First a)
-deriving instance Unboxable a => Unboxable (Data.Semigroup.Last a)
-deriving instance Unboxable a => Unboxable (Data.Semigroup.WrappedMonoid a)
-deriving instance Unboxable a => Unboxable (Data.Monoid.Dual a)
-deriving instance Unboxable Data.Monoid.All
-deriving instance Unboxable Data.Monoid.Any
-deriving instance Unboxable a => Unboxable (Data.Monoid.Sum a)
-deriving instance Unboxable a => Unboxable (Data.Monoid.Product a)
-deriving instance Unboxable a => Unboxable (Data.Ord.Down a)
+{-
+GND for type classes with associated type families is not available until GHC 8.2.
+With GHC 8.2 or later, one can derive these instances like:
+
+> deriving instance Unboxable a => Unboxable (Data.Functor.Identity.Identity a)
+> deriving instance Unboxable a => Unboxable (Data.Functor.Const.Const a b)
+> deriving instance Unboxable a => Unboxable (Data.Semigroup.Min a)
+> deriving instance Unboxable a => Unboxable (Data.Semigroup.Max a)
+> deriving instance Unboxable a => Unboxable (Data.Semigroup.First a)
+> deriving instance Unboxable a => Unboxable (Data.Semigroup.Last a)
+> deriving instance Unboxable a => Unboxable (Data.Semigroup.WrappedMonoid a)
+> deriving instance Unboxable a => Unboxable (Data.Monoid.Dual a)
+> deriving instance Unboxable Data.Monoid.All
+> deriving instance Unboxable Data.Monoid.Any
+> deriving instance Unboxable a => Unboxable (Data.Monoid.Sum a)
+> deriving instance Unboxable a => Unboxable (Data.Monoid.Product a)
+> deriving instance Unboxable a => Unboxable (Data.Ord.Down a)
+-}
+
+instance Unboxable a => Unboxable (Data.Functor.Identity.Identity a) where
+  type Rep (Data.Functor.Identity.Identity a) = Rep a
+  unboxingFrom = coerce (unboxingFrom @a)
+  unboxingTo = coerce (unboxingTo @a)
+  {-# INLINE unboxingFrom #-}
+  {-# INLINE unboxingTo #-}
+
+instance Unboxable a => Unboxable (Data.Functor.Const.Const a b) where
+  type Rep (Data.Functor.Const.Const a b) = Rep a
+  unboxingFrom = coerce (unboxingFrom @a)
+  unboxingTo = coerce (unboxingTo @a)
+  {-# INLINE unboxingFrom #-}
+  {-# INLINE unboxingTo #-}
+
+instance Unboxable a => Unboxable (Data.Semigroup.Min a) where
+  type Rep (Data.Semigroup.Min a) = Rep a
+  unboxingFrom = coerce (unboxingFrom @a)
+  unboxingTo = coerce (unboxingTo @a)
+  {-# INLINE unboxingFrom #-}
+  {-# INLINE unboxingTo #-}
+
+instance Unboxable a => Unboxable (Data.Semigroup.Max a) where
+  type Rep (Data.Semigroup.Max a) = Rep a
+  unboxingFrom = coerce (unboxingFrom @a)
+  unboxingTo = coerce (unboxingTo @a)
+  {-# INLINE unboxingFrom #-}
+  {-# INLINE unboxingTo #-}
+
+instance Unboxable a => Unboxable (Data.Semigroup.First a) where
+  type Rep (Data.Semigroup.First a) = Rep a
+  unboxingFrom = coerce (unboxingFrom @a)
+  unboxingTo = coerce (unboxingTo @a)
+  {-# INLINE unboxingFrom #-}
+  {-# INLINE unboxingTo #-}
+
+instance Unboxable a => Unboxable (Data.Semigroup.Last a) where
+  type Rep (Data.Semigroup.Last a) = Rep a
+  unboxingFrom = coerce (unboxingFrom @a)
+  unboxingTo = coerce (unboxingTo @a)
+  {-# INLINE unboxingFrom #-}
+  {-# INLINE unboxingTo #-}
+
+instance Unboxable a => Unboxable (Data.Semigroup.WrappedMonoid a) where
+  type Rep (Data.Semigroup.WrappedMonoid a) = Rep a
+  unboxingFrom = coerce (unboxingFrom @a)
+  unboxingTo = coerce (unboxingTo @a)
+  {-# INLINE unboxingFrom #-}
+  {-# INLINE unboxingTo #-}
+
+instance Unboxable a => Unboxable (Data.Monoid.Dual a) where
+  type Rep (Data.Monoid.Dual a) = Rep a
+  unboxingFrom = coerce (unboxingFrom @a)
+  unboxingTo = coerce (unboxingTo @a)
+  {-# INLINE unboxingFrom #-}
+  {-# INLINE unboxingTo #-}
+
+instance Unboxable Data.Monoid.All where
+  type Rep Data.Monoid.All = Bool
+
+instance Unboxable Data.Monoid.Any where
+  type Rep Data.Monoid.Any = Bool
+
+instance Unboxable a => Unboxable (Data.Monoid.Sum a) where
+  type Rep (Data.Monoid.Sum a) = Rep a
+  unboxingFrom = coerce (unboxingFrom @a)
+  unboxingTo = coerce (unboxingTo @a)
+  {-# INLINE unboxingFrom #-}
+  {-# INLINE unboxingTo #-}
+
+instance Unboxable a => Unboxable (Data.Monoid.Product a) where
+  type Rep (Data.Monoid.Product a) = Rep a
+  unboxingFrom = coerce (unboxingFrom @a)
+  unboxingTo = coerce (unboxingTo @a)
+  {-# INLINE unboxingFrom #-}
+  {-# INLINE unboxingTo #-}
+
+instance Unboxable a => Unboxable (Data.Ord.Down a) where
+  type Rep (Data.Ord.Down a) = Rep a
+  unboxingFrom = coerce (unboxingFrom @a)
+  unboxingTo = coerce (unboxingTo @a)
+  {-# INLINE unboxingFrom #-}
+  {-# INLINE unboxingTo #-}
+
+instance Unboxable Ordering where
+  type Rep Ordering = Int8
+  unboxingFrom x = fromIntegral (fromEnum x)
+  unboxingTo y = toEnum (fromIntegral y)
+  {-# INLINE unboxingFrom #-}
+  {-# INLINE unboxingTo #-}
diff --git a/src/Data/Vector/Unboxing/Mutable.hs b/src/Data/Vector/Unboxing/Mutable.hs
--- a/src/Data/Vector/Unboxing/Mutable.hs
+++ b/src/Data/Vector/Unboxing/Mutable.hs
@@ -4,6 +4,8 @@
   ,STVector
   ,Unboxable(Rep)
   ,Generics(..)
+  ,Enum(..)
+  ,EnumRep(..)
   -- * Accessors
   -- ** Length information
   ,length,null
diff --git a/test-deriving-via/Enum.hs b/test-deriving-via/Enum.hs
new file mode 100644
--- /dev/null
+++ b/test-deriving-via/Enum.hs
@@ -0,0 +1,13 @@
+{-# LANGUAGE DerivingVia #-}
+{-# LANGUAGE UndecidableInstances #-}
+module Enum where
+import qualified Data.Vector.Unboxing as V
+import Data.Int
+
+data OrderingEq = LT | LE | EQ | GE | GT
+  deriving (Eq, Ord, Enum, Bounded, Read, Show)
+  deriving V.Unboxable via V.Enum OrderingEq
+
+data Direction = North | South | East | West
+  deriving (Eq, Ord, Enum, Bounded, Read, Show)
+  deriving V.Unboxable via V.EnumRep Int8 Direction
diff --git a/test-deriving-via/Foo.hs b/test-deriving-via/Foo.hs
new file mode 100644
--- /dev/null
+++ b/test-deriving-via/Foo.hs
@@ -0,0 +1,66 @@
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+module Foo
+  (Foo -- the constructor is not exported!
+  ,mkFoo
+  ) where
+import Data.Vector.Unboxing (Unboxable(..))
+import qualified Data.Vector.Unboxed as U
+import qualified Data.Vector.Unboxed.Mutable as UM
+import qualified Data.Vector.Generic as G
+import qualified Data.Vector.Generic.Mutable as GM
+import Control.DeepSeq (NFData)
+import GHC.Generics
+import Data.Coerce
+
+newtype Foo = Foo Int deriving (Eq,Show,Generic)
+
+instance NFData Foo
+
+mkFoo :: Foo
+mkFoo = Foo 42
+
+-- Comparison of Data.Vector.Unboxing and Data.Vector.Unboxed:
+
+-- The number of lines needed to enable 'Data.Vector.Unboxing.Vector Foo' is ...
+
+instance Unboxable Foo where
+  type Rep Foo = Int -- needs TypeFamilies here
+
+-- ... only 2 lines!
+-- Also, you can use GeneralizedNewtypeDeriving + UndecidableInstances if you want to write less.
+
+-- On the other hand, the number of lines needed to enable 'Data.Vector.Unboxed.Vector Foo' is ...
+
+newtype instance UM.MVector s Foo = MV_Foo (UM.MVector s Int)
+newtype instance U.Vector Foo = V_Foo (U.Vector Int)
+
+instance GM.MVector UM.MVector Foo where -- needs MultiParamTypeClasses here
+  basicLength (MV_Foo mv) = GM.basicLength mv
+  basicUnsafeSlice i l (MV_Foo mv) = MV_Foo (GM.basicUnsafeSlice i l mv)
+  basicOverlaps (MV_Foo mv) (MV_Foo mv') = GM.basicOverlaps mv mv'
+  basicUnsafeNew l = MV_Foo <$> GM.basicUnsafeNew l
+  basicInitialize (MV_Foo mv) = GM.basicInitialize mv
+  basicUnsafeReplicate i x = MV_Foo <$> GM.basicUnsafeReplicate i (coerce x)
+  basicUnsafeRead (MV_Foo mv) i = coerce <$> GM.basicUnsafeRead mv i
+  basicUnsafeWrite (MV_Foo mv) i x = GM.basicUnsafeWrite mv i (coerce x)
+  basicClear (MV_Foo mv) = GM.basicClear mv
+  basicSet (MV_Foo mv) x = GM.basicSet mv (coerce x)
+  basicUnsafeCopy (MV_Foo mv) (MV_Foo mv') = GM.basicUnsafeCopy mv mv'
+  basicUnsafeMove (MV_Foo mv) (MV_Foo mv') = GM.basicUnsafeMove mv mv'
+  basicUnsafeGrow (MV_Foo mv) n = MV_Foo <$> GM.basicUnsafeGrow mv n
+
+instance G.Vector U.Vector Foo where -- needs MultiParamTypeClasses here
+  basicUnsafeFreeze (MV_Foo mv) = V_Foo <$> G.basicUnsafeFreeze mv
+  basicUnsafeThaw (V_Foo v) = MV_Foo <$> G.basicUnsafeThaw v
+  basicLength (V_Foo v) = G.basicLength v
+  basicUnsafeSlice i l (V_Foo v) = V_Foo (G.basicUnsafeSlice i l v)
+  basicUnsafeIndexM (V_Foo v) i = coerce <$> G.basicUnsafeIndexM v i
+  basicUnsafeCopy (MV_Foo mv) (V_Foo v) = G.basicUnsafeCopy mv v
+  elemseq (V_Foo v) x y = G.elemseq v (coerce x) y
+
+instance U.Unbox Foo
+
+-- ... enormous!
+-- Unfortunately, you cannot use GeneralizedNewtypeDeriving to MVector/Vector classes.
diff --git a/test-deriving-via/Generic.hs b/test-deriving-via/Generic.hs
new file mode 100644
--- /dev/null
+++ b/test-deriving-via/Generic.hs
@@ -0,0 +1,34 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE DerivingVia #-}
+{-# LANGUAGE UndecidableInstances #-}
+module Generic where
+import Test.HUnit
+import qualified Data.Vector.Unboxing as V
+import GHC.Generics
+import Foo (Foo,mkFoo)
+import Enum (Direction(North))
+
+-- Deriving using Generic
+data ComplexDouble = ComplexDouble { realPartD :: {-# UNPACK #-} !Double
+                                   , imagPartD :: {-# UNPACK #-} !Double
+                                   }
+  deriving (Eq,Show,Generic)
+  deriving V.Unboxable via V.Generics ComplexDouble
+
+testComplexDouble = TestCase $ do
+  let v :: V.Vector ComplexDouble
+      v = V.singleton (ComplexDouble 1.0 2.0)
+      x :: V.Vector Double
+      x = V.map realPartD v
+  assertEqual "construction" (ComplexDouble 1.0 2.0) (V.head v)
+  assertEqual "map" (V.singleton 1.0) x
+
+data Bar = Bar {-# UNPACK #-} !Foo {-# UNPACK #-} !Double !Direction
+  deriving (Eq,Show,Generic)
+  deriving V.Unboxable via V.Generics Bar
+
+testBar = TestCase $ do
+  let v :: V.Vector Bar
+      v = V.singleton (Bar mkFoo 3.14 North)
+  assertEqual "construction" (Bar mkFoo 3.14 North) (V.head v)
+  assertEqual "map" (V.singleton mkFoo) (V.map (\(Bar foo _ _) -> foo) v)
diff --git a/test-deriving-via/Spec.hs b/test-deriving-via/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test-deriving-via/Spec.hs
@@ -0,0 +1,11 @@
+import Prelude
+import Test.HUnit
+---
+import Generic
+import Enum
+
+tests = TestList [TestLabel "Test with generic 1" testComplexDouble
+                 ,TestLabel "Test with generic 2" testBar
+                 ]
+
+main = runTestTT tests
diff --git a/test-deriving-via/TestTypeErrors.hs b/test-deriving-via/TestTypeErrors.hs
new file mode 100644
--- /dev/null
+++ b/test-deriving-via/TestTypeErrors.hs
@@ -0,0 +1,19 @@
+-- {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE DerivingVia #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# OPTIONS_GHC -fdefer-type-errors -Wno-deferred-type-errors #-}
+module TestTypeErrors where
+import Test.HUnit
+import Test.ShouldNotTypecheck
+import qualified Data.Vector.Unboxing as V
+import GHC.Generics
+
+data Animal = Dog | Cat
+  deriving (Eq,Show,Generic)
+  deriving V.Unboxable via V.Generics Animal
+
+testTypeErrors :: Test
+testTypeErrors = TestList [TestLabel "Test generic deriving for a sum type" $ TestCase $ shouldNotTypecheck (V.singleton Dog)
+                          ]
+
diff --git a/test-gnd/Foo.hs b/test-gnd/Foo.hs
new file mode 100644
--- /dev/null
+++ b/test-gnd/Foo.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE UndecidableInstances #-}
+module Foo
+  (Foo -- the constructor is not exported!
+  ,mkFoo
+  ) where
+import Data.Vector.Unboxing (Unboxable(..))
+import Control.DeepSeq (NFData)
+import GHC.Generics
+
+newtype Foo = Foo Int deriving (Eq,Show,Generic,Unboxable)
+
+instance NFData Foo
+
+mkFoo :: Foo
+mkFoo = Foo 42
diff --git a/test-gnd/Spec.hs b/test-gnd/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test-gnd/Spec.hs
@@ -0,0 +1,56 @@
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE DerivingStrategies #-}
+{-# LANGUAGE UndecidableInstances #-}
+import Prelude
+import Test.HUnit
+import qualified Data.Vector.Unboxing as V
+import Data.Monoid (Sum(..))
+import Data.MonoTraversable (ofold)
+---
+import Foo (Foo,mkFoo)
+
+newtype IntMod17 = IntMod17 Int
+  deriving (Eq,Show)
+  deriving newtype V.Unboxable -- with DerivingStrategies
+
+instance Num IntMod17 where
+  IntMod17 x + IntMod17 y = IntMod17 ((x + y) `rem` 17)
+  IntMod17 x - IntMod17 y = IntMod17 ((x - y) `mod` 17)
+  IntMod17 x * IntMod17 y = IntMod17 ((x * y) `rem` 17)
+  negate (IntMod17 x) = IntMod17 (negate x `mod` 17)
+  fromInteger x = IntMod17 (fromIntegral (x `mod` 17))
+  abs = undefined; signum = undefined
+
+testIntMod17 = TestCase $ do
+  let v = V.fromList [-3,-2,-1,0,1,2,3,4,5] :: V.Vector IntMod17
+  assertEqual "construction" (V.fromList [14,15,16,0,1,2,3,4,5]) v
+  assertEqual "sum" 9 (V.sum v) -- not 60
+  assertEqual "coercion" (V.fromList [14,15,16,0,1,2,3,4,5] :: V.Vector Int) (V.coerceVector v) -- this is possible because the constructor of IntMod17 is visible here
+  let vSum = V.coerceVector v :: V.Vector (Sum IntMod17)
+  assertEqual "coercion and sum" (Sum 9) (ofold vSum)
+
+newtype Baz = Baz Foo
+  deriving (Eq,Show,V.Unboxable)
+
+testBaz = TestCase $ do
+  let foo :: V.Vector Foo
+      foo = V.singleton mkFoo
+      baz :: V.Vector Baz
+      baz = V.singleton (Baz mkFoo)
+  assertEqual "construction" (Baz mkFoo) (V.head baz)
+  assertEqual "map 1" baz (V.map Baz foo)
+  assertEqual "map 2" foo (V.map (\(Baz x) -> x) baz)
+  assertEqual "coercion" baz (V.coerceVector foo)
+
+-- We can make an unboxed vector of Foo, even though we don't have 'Coercible Int Foo' in scope.
+testAbstractType = TestCase $ do
+  let v = V.singleton mkFoo :: V.Vector Foo
+  assertEqual "Foo" mkFoo (V.head v)
+  assertEqual "coercion" mkFoo (getSum $ V.head (V.coerceVector v :: V.Vector (Sum Foo)))
+
+tests = TestList [TestLabel "Basic features" testIntMod17
+                 ,TestLabel "Test with abstract type" testAbstractType
+                 ,TestLabel "Test with GND" testBaz
+                 ]
+
+main = runTestTT tests
diff --git a/test/Generic.hs b/test/Generic.hs
deleted file mode 100644
--- a/test/Generic.hs
+++ /dev/null
@@ -1,33 +0,0 @@
-{-# LANGUAGE DeriveGeneric #-}
-{-# LANGUAGE DerivingVia #-}
-{-# LANGUAGE UndecidableInstances #-}
-module Generic where
-import Test.HUnit
-import qualified Data.Vector.Unboxing as V
-import GHC.Generics
-import Foo (Foo,mkFoo)
-
--- Deriving using Generic
-data ComplexDouble = ComplexDouble { realPartD :: {-# UNPACK #-} !Double
-                                   , imagPartD :: {-# UNPACK #-} !Double
-                                   }
-  deriving (Eq,Show,Generic)
-  deriving V.Unboxable via V.Generics ComplexDouble
-
-testComplexDouble = TestCase $ do
-  let v :: V.Vector ComplexDouble
-      v = V.singleton (ComplexDouble 1.0 2.0)
-      x :: V.Vector Double
-      x = V.map realPartD v
-  assertEqual "construction" (ComplexDouble 1.0 2.0) (V.head v)
-  assertEqual "map" (V.singleton 1.0) x
-
-data Bar = Bar {-# UNPACK #-} !Foo {-# UNPACK #-} !Double
-  deriving (Eq,Show,Generic)
-  deriving V.Unboxable via V.Generics Bar
-
-testBar = TestCase $ do
-  let v :: V.Vector Bar
-      v = V.singleton (Bar mkFoo 3.14)
-  assertEqual "construction" (Bar mkFoo 3.14) (V.head v)
-  assertEqual "map" (V.singleton mkFoo) (V.map (\(Bar foo _) -> foo) v)
diff --git a/test/Loop.hs b/test/Loop.hs
new file mode 100644
--- /dev/null
+++ b/test/Loop.hs
@@ -0,0 +1,33 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE DerivingStrategies #-}
+-- {-# LANGUAGE DerivingVia #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE TypeFamilies #-}
+module Loop where
+import qualified Data.Vector.Unboxing as V
+import GHC.Generics
+
+-- Loop!
+{-
+newtype Bad = Bad Bad
+  deriving newtype V.Unboxable
+-}
+
+{-
+data Bad2 = Bad2 Bad2
+  deriving Generic
+  deriving V.Unboxable via V.Generics Bad2
+-}
+
+{-
+class SomeClass a where
+  type Foo a
+--   foo :: a -> Foo a
+
+newtype Bad = Bad Bad
+  deriving newtype SomeClass
+
+newtype BadT = BadT (Int, BadT)
+  deriving newtype V.Unboxable
+-}
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -11,7 +11,6 @@
 ---
 import TestTypeErrors
 import Foo (Foo,mkFoo)
-import Generic
 
 testInt = TestCase $ do
   let v = V.fromList [2,-5,42] :: V.Vector Int
@@ -21,7 +20,6 @@
 
 newtype IntMod17 = IntMod17 Int
   deriving (Eq,Show)
---  deriving newtype VF.Unboxable
 
 instance V.Unboxable IntMod17 where
   type Rep IntMod17 = Int
@@ -42,19 +40,6 @@
   let vSum = V.coerceVector v :: V.Vector (Sum IntMod17)
   assertEqual "coercion and sum" (Sum 9) (ofold vSum)
 
-newtype Baz = Baz Foo
-  deriving (Eq,Show,V.Unboxable)
-
-testBaz = TestCase $ do
-  let foo :: V.Vector Foo
-      foo = V.singleton mkFoo
-      baz :: V.Vector Baz
-      baz = V.singleton (Baz mkFoo)
-  assertEqual "construction" (Baz mkFoo) (V.head baz)
-  assertEqual "map 1" baz (V.map Baz foo)
-  assertEqual "map 2" foo (V.map (\(Baz x) -> x) baz)
-  assertEqual "coercion" baz (V.coerceVector foo)
-
 -- We can make an unboxed vector of Foo, even though we don't have 'Coercible Int Foo' in scope.
 testAbstractType = TestCase $ do
   let v = V.singleton mkFoo :: V.Vector Foo
@@ -65,10 +50,6 @@
                  ,TestLabel "Conversion with Data.Vector.Unboxed" testInt
                  ,TestLabel "Test with abstract type" testAbstractType
                  ,TestLabel "Check for type errors" testTypeErrors
-                 ,TestLabel "Test with generic 1" testComplexDouble
-                 ,TestLabel "Test with generic 2" testBar
-                 ,TestLabel "Test with GND" testBaz
                  ]
 
 main = runTestTT tests
-
diff --git a/test/TestTypeErrors.hs b/test/TestTypeErrors.hs
--- a/test/TestTypeErrors.hs
+++ b/test/TestTypeErrors.hs
@@ -1,7 +1,4 @@
 {-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE DeriveGeneric #-}
-{-# LANGUAGE DerivingVia #-}
-{-# LANGUAGE UndecidableInstances #-}
 {-# OPTIONS_GHC -fdefer-type-errors -Wno-deferred-type-errors #-}
 module TestTypeErrors where
 import Test.HUnit
@@ -9,7 +6,6 @@
 import Data.Coerce
 import qualified Data.Vector.Unboxing as V
 import Foo (Foo)
-import GHC.Generics
 
 -- Since the module Foo does not export Foo's constructor,
 -- it should be impossible to create a value of Foo in this module.
@@ -30,14 +26,9 @@
 intToFoo3 :: (V.Unboxable a, a ~ Foo) => Int -> a
 intToFoo3 x = coerce x
 
-data Animal = Dog | Cat
-  deriving (Eq,Show,Generic)
-  deriving V.Unboxable via V.Generics Animal
-
 testTypeErrors :: Test
 testTypeErrors = TestList [TestLabel "Basic test for coerce" $ TestCase $ shouldNotTypecheck (intToFoo1 0xDEAD)
                           ,TestLabel "Test for coerceVector" $ TestCase $ shouldNotTypecheck (intToFoo2 0xDEAD)
                           ,TestLabel "Test for Unboxable" $ TestCase $ shouldNotTypecheck (intToFoo3 0xDEAD)
-                          ,TestLabel "Test generic deriving for a sum type" $ TestCase $ shouldNotTypecheck (V.singleton Dog)
                           ]
 
diff --git a/unboxing-vector.cabal b/unboxing-vector.cabal
--- a/unboxing-vector.cabal
+++ b/unboxing-vector.cabal
@@ -4,11 +4,11 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 6f43e3e12c9aa312cf1e18e1bc60132a5cb9878c463bd2b9863a20ea6c7125cf
+-- hash: 8fec698d5a4391032074d2a71e767bc6f667b179e962ed429de29ca13c44b918
 
 name:           unboxing-vector
-version:        0.1.0.0
-synopsis:       Newtype-friendly Unboxed Vectors
+version:        0.1.1.0
+synopsis:       A newtype-friendly variant of unboxed vectors
 description:    Please see the README on GitHub at <https://github.com/minoki/unboxing-vector#readme>
 category:       Data, Data Structures
 homepage:       https://github.com/minoki/unboxing-vector#readme
@@ -49,7 +49,7 @@
   main-is: Spec.hs
   other-modules:
       Foo
-      Generic
+      Loop
       TestTypeErrors
       Paths_unboxing_vector
   hs-source-dirs:
@@ -64,6 +64,56 @@
     , should-not-typecheck
     , unboxing-vector
     , vector
+  default-language: Haskell2010
+
+test-suite unboxing-vector-test-deriving-via
+  type: exitcode-stdio-1.0
+  main-is: Spec.hs
+  other-modules:
+      Enum
+      Foo
+      Generic
+      TestTypeErrors
+      Paths_unboxing_vector
+  hs-source-dirs:
+      test-deriving-via
+  ghc-options: -Wall -Wno-missing-signatures
+  build-depends:
+      HUnit
+    , base >=4.9 && <5
+    , deepseq
+    , mono-traversable
+    , primitive
+    , should-not-typecheck
+    , unboxing-vector
+    , vector
+  if impl(ghc >= 8.6.1)
+    buildable: True
+  else
+    buildable: False
+  default-language: Haskell2010
+
+test-suite unboxing-vector-test-gnd
+  type: exitcode-stdio-1.0
+  main-is: Spec.hs
+  other-modules:
+      Foo
+      Paths_unboxing_vector
+  hs-source-dirs:
+      test-gnd
+  ghc-options: -Wall -Wno-missing-signatures
+  build-depends:
+      HUnit
+    , base >=4.9 && <5
+    , deepseq
+    , mono-traversable
+    , primitive
+    , unboxing-vector
+    , vector
+  if impl(ghc >= 8.2.1)
+    buildable: True
+  else
+    buildable: False
   default-language: Haskell2010
 
 benchmark unboxing-vector-benchmark
