diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 0.2.0
+
+- `massiv-0.4` minimum bound.
+- GHC 8.8 compatibility.
+
 ## 0.1.2
 
 - GHC 8.6 compatibility. Requires `massiv` of at least version `0.2`.
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright Colin Woodbury (c) 2017
+Copyright Colin Woodbury (c) 2018 - 2020
 
 All rights reserved.
 
diff --git a/bench/Bench.hs b/bench/Bench.hs
--- a/bench/Bench.hs
+++ b/bench/Bench.hs
@@ -6,7 +6,6 @@
 import           Criterion.Main
 import           Data.List.NonEmpty (NonEmpty(..))
 import           Data.Massiv.Array as A hiding (zipWith)
-import           Data.Monoid ((<>))
 import qualified Data.Vector as V
 import qualified Data.Vector.Unboxed as U
 import           Geography.MapAlgebra
@@ -79,8 +78,8 @@
   , bench "zipWith (/)"    $ nf (_array . strict S . zipWith (/) rF) gF
   , bench "(+)"            $ nf (_array . strict S . (+ lazy r)) (lazy g)
   , bench "(/)"            $ nf (_array . strict S . (/ lazy rF)) (lazy gF)
-  , bench "(.+)"           $ nf (\g' -> computeAs S $ _array r .+ g') (_array g)
-  , bench "(./)"           $ nf (\g' -> computeAs S $ _array rF ./ g') (_array gF)
+  -- , bench "(.+)"           $ nf (\g' -> computeAs S $ _array r .+ g') (_array g)
+  -- , bench "(./)"           $ nf (\g' -> computeAs S $ _array rF ./ g') (_array gF)
   , bench "lmax"           $ nf (_array . strict S . lmax img) img
   , bench "lmin"           $ nf (_array . strict S . lmin img) img
   , bench "lmean (Word8)"  $ nf (_array . strict S . lmean @Word8 @Double) rs
diff --git a/lib/Geography/MapAlgebra.hs b/lib/Geography/MapAlgebra.hs
--- a/lib/Geography/MapAlgebra.hs
+++ b/lib/Geography/MapAlgebra.hs
@@ -15,7 +15,7 @@
 
 -- |
 -- Module    : Geography.MapAlgebra
--- Copyright : (c) Colin Woodbury, 2018 - 2019
+-- Copyright : (c) Colin Woodbury, 2018 - 2020
 -- License   : BSD3
 -- Maintainer: Colin Woodbury <colin@fosskers.ca>
 --
@@ -285,7 +285,6 @@
 import           Data.Bits (testBit)
 import           Data.Bool (bool)
 import qualified Data.ByteString.Lazy as BL
-import           Data.Default (Default, def)
 import           Data.Foldable
 import qualified Data.List as L
 import           Data.List.NonEmpty (NonEmpty(..))
@@ -387,9 +386,9 @@
 
 -- | Warning: This will evaluate (at most) the 10x10 top-left corner of your
 -- `Raster` for display. This should only be used for debugging.
-instance (Show a, Load (EltRepr u Ix2) Ix2 a, Size u Ix2 a) => Show (Raster u p r c a) where
-  show (Raster a) = show . computeAs B $ extract' zeroIndex (r :. c) a
-    where (r :. c) = liftIndex (P.min 10) $ size a
+instance (Show a, Load (R u) Ix2 a, Extract u Ix2 a) => Show (Raster u p r c a) where
+  show (Raster a) = show . computeAs B $ extract' zeroIndex (Sz2 (P.min 10 r) (P.min 10 c)) a
+    where Sz (r :. c) = size a
 
 instance (Eq a, Unbox a) => Eq (Raster U p r c a) where
   Raster a == Raster b = a == b
@@ -485,7 +484,7 @@
   {-# INLINE product #-}
 
   -- | \(\mathcal{O}(1)\).
-  length (Raster a) = (\(r :. c) -> r * c) $ A.size a
+  length (Raster a) = (\(Sz2 r c) -> r * c) $ A.size a
   {-# INLINE length #-}
 
 -- | \(\mathcal{O}(1)\). Force a `Raster`'s representation to `D`, allowing it
@@ -515,7 +514,7 @@
 -- number respectively.
 fromFunction :: forall u p r c a. (KnownNat r, KnownNat c, Construct u Ix2 a) =>
   u -> Comp -> (Ix2 -> a) -> Raster u p r c a
-fromFunction u c f = Raster $ makeArrayR u c sh f
+fromFunction u c f = Raster $ makeArrayR u c (Sz sh) f
   where sh = fromInteger (natVal (Proxy :: Proxy r)) :. fromInteger (natVal (Proxy :: Proxy c))
 {-# INLINE fromFunction #-}
 
@@ -524,7 +523,8 @@
 -- the `Raster`.
 fromVector :: forall v p r c a. (KnownNat r, KnownNat c, GV.Vector v a, Mutable (A.ARepr v) Ix2 a, Typeable v) =>
   Comp -> v a -> Either String (Raster (A.ARepr v) p r c a)
-fromVector comp v | (r * c) == GV.length v = Right . Raster $ A.fromVector comp (r :. c) v
+-- fromVector comp v | (r * c) == GV.length v = Right . Raster $ A.fromVector comp (r :. c) v
+fromVector comp v | (r * c) == GV.length v = Right . Raster $ A.fromVector' comp (Sz2 r c) v
                   | otherwise = Left $ printf "Expected Pixel Count: %d - Actual: %d" (r * c) (GV.length v)
   where r = fromInteger $ natVal (Proxy :: Proxy r)
         c = fromInteger $ natVal (Proxy :: Proxy c)
@@ -548,7 +548,7 @@
   img <- setComp (bool Par Seq $ cap == 1) <$> readImageAuto fp
   let rows = fromInteger $ natVal (Proxy :: Proxy r)
       cols = fromInteger $ natVal (Proxy :: Proxy c)
-      (r :. c) = size img
+      Sz (r :. c) = size img
   if r == rows && c == cols
     then do
     (ar, ag, ab, aa) <- spreadRGBA img
@@ -565,7 +565,7 @@
   mb <- A.unsafeNew sz
   mg <- A.unsafeNew sz
   ma <- A.unsafeNew sz
-  flip A.imapP_ arr $ \i (PixelRGBA r g b a) -> do
+  flip A.imapM_ arr $ \i (PixelRGBA r g b a) -> do
     A.unsafeWrite mr i r
     A.unsafeWrite mg i g
     A.unsafeWrite mb i b
@@ -585,10 +585,10 @@
   img <- setComp (bool Par Seq $ cap == 1) <$> readImageAuto fp
   let rows = fromInteger $ natVal (Proxy :: Proxy r)
       cols = fromInteger $ natVal (Proxy :: Proxy c)
-      (r :. c) = size img
+      Sz (r :. c) = size img
   pure . bool (Left $ printf "Expected Size: %d x %d - Actual Size: %d x %d" rows cols r c) (Right $ f img) $ r == rows && c == cols
   where f :: Image S Y a -> Raster S p r c a
-        f img = Raster . A.fromVector (getComp img) (size img) . VS.unsafeCast $ A.toVector img
+        f img = Raster . A.fromVector' (getComp img) (size img) . VS.unsafeCast $ A.toVector img
 {-# INLINE fromGray #-}
 
 -- | An invisible pixel (alpha channel set to 0).
@@ -702,12 +702,12 @@
 
 -- | The count of unique values at each shared index.
 lvariety :: (KnownNat r, KnownNat c, Eq a) => NonEmpty (Raster D p r c a) -> Raster D p r c Word
-lvariety = fmap (fromIntegral . length . NE.nub) . sequenceA
+lvariety = fmap (fromIntegral . length . NE.nub) . P.sequenceA
 {-# INLINE lvariety #-}
 
 -- | The most frequently appearing value at each shared index.
 lmajority :: (KnownNat r, KnownNat c, Ord a) => NonEmpty (Raster D p r c a) -> Raster D p r c a
-lmajority = fmap majo . sequenceA
+lmajority = fmap majo . P.sequenceA
 {-# INLINE lmajority #-}
 
 -- | Find the most common value in some `Foldable`.
@@ -723,7 +723,7 @@
 
 -- | The least frequently appearing value at each shared index.
 lminority :: (KnownNat r, KnownNat c, Ord a) => NonEmpty (Raster D p r c a) -> Raster D p r c a
-lminority = fmap mino . sequenceA
+lminority = fmap mino . P.sequenceA
 {-# INLINE lminority #-}
 
 -- | Find the least common value in some `Foldable`.
@@ -743,7 +743,7 @@
   :: forall p a r c. (Real a, KnownNat r, KnownNat c)
   => NonEmpty (Raster D p r c a) -> Maybe (Raster D p r c Double)
 lvariance (_ :| []) = Nothing
-lvariance rs = Just (f <$> sequenceA rs)
+lvariance rs = Just (f <$> P.sequenceA rs)
   where
     len :: Double
     len = realToFrac $ length rs
@@ -995,7 +995,7 @@
 {-# INLINE fpartition #-}
 
 partStencil :: (Eq a, Default a) => Stencil Ix2 a Corners
-partStencil = makeStencil (2 :. 2) (1 :. 0) $ \f -> do
+partStencil = makeStencil (Sz2 2 2) (1 :. 0) $ \f -> do
   tl <- f (-1 :. 0)
   tr <- f (-1 :. 1)
   br <- f (0  :. 1)
@@ -1076,12 +1076,12 @@
 {-# INLINE neighbourhood #-}
 
 neighbourhoodStencil :: Default a => (a -> a -> a -> a -> a -> a -> a -> a -> a -> b) -> Stencil Ix2 a b
-neighbourhoodStencil f = makeStencil (3 :. 3) (1 :. 1) (neighbourhood f)
+neighbourhoodStencil f = makeStencil (Sz2 3 3) (1 :. 1) (neighbourhood f)
 {-# INLINE neighbourhoodStencil #-}
 
 -- | Get the surficial facets for each pixel and apply some function to them.
 facetStencil :: (Fractional a, Default a) => (a -> a -> a -> a -> a -> a -> a -> a -> a -> b) -> Stencil Ix2 a b
-facetStencil f = makeStencil (3 :. 3) (1 :. 1) (neighbourhood g)
+facetStencil f = makeStencil (Sz2 3 3) (1 :. 1) (neighbourhood g)
   where g nw no ne we fo ea sw so se = f ((nw + no + we + fo) / 4)
                                          ((no + fo) / 2)
                                          ((no + ne + fo + ea) / 4)
@@ -1311,7 +1311,7 @@
 -- | Given a `Histogram`, produce a list of "colour breaks" as needed by
 -- functions like `greenRed`.
 breaks :: Histogram -> [Word8]
-breaks (Histogram h) = take 10 . (1 :) . reverse . snd . VS.ifoldl' f (binWidth, []) . VS.postscanl' (+) 0 $ VS.tail h
+breaks (Histogram h) = take 10 . (1 :) . P.reverse . snd . VS.ifoldl' f (binWidth, []) . VS.postscanl' (+) 0 $ VS.tail h
   where binWidth     = VS.sum (VS.tail h) `div` 11  -- Yes, 11 and not 10.
         f a@(goal, acc) i n | n > goal  = (next n goal, (fromIntegral i + 1) : acc)
                             | otherwise = a
diff --git a/mapalgebra.cabal b/mapalgebra.cabal
--- a/mapalgebra.cabal
+++ b/mapalgebra.cabal
@@ -1,87 +1,80 @@
-cabal-version: 1.12
-
--- This file has been generated from package.yaml by hpack version 0.31.1.
---
--- see: https://github.com/sol/hpack
---
--- hash: b630ea7d1badb749610908c0e84eb22c8a43221840a21217892279d6808a07af
+cabal-version:      2.2
+name:               mapalgebra
+version:            0.2.0
+synopsis:           Efficient, polymorphic Map Algebra.
+description:
+  Efficient, polymorphic Map Algebra.
+  .
+  This library is an implementation of /Map Algebra/ as described in the book
+  /GIS and Cartographic Modeling/ by Dana Tomlin. The fundamental type, the
+  `Raster`, is typesafe. Rasters of different size and projection are considered
+  different types, and so cannot be combined mistakenly in any way.
+  .
+  Also featured are op fusion (i.e. "lazy Rasters"), extremely fast Focal
+  Operations, and typesafe NoData handling. Please see the main module for a
+  more detailed introduction.
 
-name:           mapalgebra
-version:        0.1.2
-synopsis:       Efficient, polymorphic Map Algebra.
-description:    Efficient, polymorphic Map Algebra.
-                .
-                This library is an implementation of /Map Algebra/ as described in the book /GIS and Cartographic Modeling/ by Dana Tomlin. The fundamental type, the `Raster`, is typesafe. Rasters of different size and projection are considered different types, and so cannot be combined mistakenly in any way.
-                .
-                Also featured are op fusion (i.e. "lazy Rasters"), extremely fast Focal Operations, and typesafe NoData handling. Please see the main module for a more detailed introduction.
-category:       Geography
-homepage:       https://github.com/fosskers/mapalgebra
-author:         Colin Woodbury
-maintainer:     colin@fosskers.ca
-copyright:      2018 Colin Woodbury
-license:        BSD3
-license-file:   LICENSE
-build-type:     Simple
+category:           Geography
+homepage:           https://github.com/fosskers/mapalgebra
+author:             Colin Woodbury
+maintainer:         colin@fosskers.ca
+copyright:          2018 - 2020 Colin Woodbury
+license:            BSD-3-Clause
+license-file:       LICENSE
+build-type:         Simple
 extra-source-files:
-    README.md
-    CHANGELOG.md
-    data/512x512.tif
-    data/gray.png
-    data/gray512.tif
-    data/spectrum.png
+  README.md
+  CHANGELOG.md
+  data/512x512.tif
+  data/gray.png
+  data/gray512.tif
+  data/spectrum.png
 
+common commons
+  default-language: Haskell2010
+  ghc-options:
+    -Wall -Wincomplete-record-updates -Wincomplete-uni-patterns
+    -Wredundant-constraints
+
+  build-depends:
+    , base     >=4.10 && <4.14
+    , hmatrix  >=0.18 && <0.21
+    , massiv   ^>=0.4
+    , vector   >=0.11 && <0.13
+
 library
-  hs-source-dirs:
-      lib
-  ghc-options: -Wall -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints
+  import:          commons
+  hs-source-dirs:  lib
   build-depends:
-      base >=4.10 && <4.13
     , bytestring
     , containers
-    , data-default
     , deepseq
-    , hmatrix >=0.18 && <0.20
-    , massiv >=0.2 && <0.3
-    , massiv-io >=0.1 && <0.2
-    , vector >=0.11 && <0.13
-  exposed-modules:
-      Geography.MapAlgebra
-  default-language: Haskell2010
+    , massiv-io   ^>=0.1
 
+  exposed-modules: Geography.MapAlgebra
+
 test-suite mapalgebra-test
-  type: exitcode-stdio-1.0
-  main-is: Test.hs
-  hs-source-dirs:
-      test
-  ghc-options: -Wall -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints -threaded -with-rtsopts=-N
+  import:         commons
+  type:           exitcode-stdio-1.0
+  main-is:        Test.hs
+  hs-source-dirs: test
+  ghc-options:    -threaded -with-rtsopts=-N
   build-depends:
-      HUnit-approx >=1.1 && <1.2
-    , QuickCheck
-    , base >=4.10 && <4.13
     , containers
-    , hmatrix >=0.18 && <0.20
+    , HUnit-approx      ^>=1.1
     , mapalgebra
-    , massiv >=0.2 && <0.3
-    , massiv-io >=0.1 && <0.2
-    , tasty >=0.11 && <2.0
-    , tasty-hunit >=0.9 && <0.11
-    , tasty-quickcheck >=0.8 && <0.11
-    , vector >=0.11 && <0.13
-  default-language: Haskell2010
+    , QuickCheck
+    , tasty             >=0.11 && <2.0
+    , tasty-hunit       >=0.9  && <0.11
+    , tasty-quickcheck  >=0.8  && <0.11
 
 benchmark mapalgebra-bench
-  type: exitcode-stdio-1.0
-  main-is: Bench.hs
-  hs-source-dirs:
-      bench
-  ghc-options: -Wall -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints -threaded -O2 -with-rtsopts=-N
+  import:         commons
+  type:           exitcode-stdio-1.0
+  main-is:        Bench.hs
+  hs-source-dirs: bench
+  ghc-options:    -threaded -O2 -with-rtsopts=-N
   build-depends:
-      base >=4.10 && <4.13
-    , containers
-    , criterion >=1.1 && <1.6
-    , hmatrix >=0.18 && <0.20
+    , criterion   >=1.1 && <1.6
     , mapalgebra
-    , massiv >=0.2 && <0.3
-    , massiv-io >=0.1 && <0.2
-    , vector >=0.11 && <0.13
-  default-language: Haskell2010
+    , massiv-io   ^>=0.1
