diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,13 @@
+# 0.5.0.0 (2019-05-09)
+
+* Add `ejections` that computes a product of functions
+  that try to extract an element out of an n-ary sum.
+  (See #91.)
+
+* Change the definition of `SameShapeAs` to be
+  non-recursive and thereby improve compiler performance.
+  (See #105.)
+
 # 0.4.0.0 (2018-10-20)
 
 * Split into `sop-core` and `generics-sop` packages.
diff --git a/Setup.hs b/Setup.hs
deleted file mode 100644
--- a/Setup.hs
+++ /dev/null
@@ -1,2 +0,0 @@
-import Distribution.Simple
-main = defaultMain
diff --git a/sop-core.cabal b/sop-core.cabal
--- a/sop-core.cabal
+++ b/sop-core.cabal
@@ -1,5 +1,5 @@
 name:                sop-core
-version:             0.4.0.0
+version:             0.5.0.0
 synopsis:            True Sums of Products
 description:
   Implementation of n-ary sums and n-ary products.
@@ -25,7 +25,7 @@
 build-type:          Simple
 cabal-version:       >=1.10
 extra-source-files:  CHANGELOG.md doctest.sh
-tested-with:         GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.3, GHC == 8.6.1
+tested-with:         GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.4, GHC == 8.6.5
 
 source-repository head
   type:                git
diff --git a/src/Data/SOP.hsig b/src/Data/SOP.hsig
new file mode 100644
--- /dev/null
+++ b/src/Data/SOP.hsig
@@ -0,0 +1,7 @@
+signature Data.SOP where
+
+data NP :: (k -> Type) -> [k] -> Type where
+  Nil  :: NP f '[]
+  (:*) :: f x -> NP f xs -> NP f (x ': xs)
+
+infixr 5 :*
diff --git a/src/Data/SOP/Constraint.hs b/src/Data/SOP/Constraint.hs
--- a/src/Data/SOP/Constraint.hs
+++ b/src/Data/SOP/Constraint.hs
@@ -149,7 +149,7 @@
 --
 type All2 c = All (All c)
 
--- | Require a constraint for pointwise for every pair of
+-- | Require a constraint pointwise for every pair of
 -- elements from two lists.
 --
 -- /Example:/ The constraint
@@ -186,16 +186,22 @@
 -- | Type family that forces a type-level list to be of the same
 -- shape as the given type-level list.
 --
+-- Since 0.5.0.0, this only tests the top-level structure of
+-- the list, and is intended to be used in conjunction with
+-- a separate construct (such as the 'AllZip', 'AllZipF'
+-- combination to tie the recursive knot). The reason is that
+-- making 'SameShapeAs' directly recursive leads to quadratic
+-- compile times.
+--
 -- The main use of this constraint is to help type inference to
 -- learn something about otherwise unknown type-level lists.
 --
--- @since 0.3.1.0
+-- @since 0.5.0.0
 --
 type family
   SameShapeAs (xs :: [a]) (ys :: [b]) :: Constraint where
   SameShapeAs '[]       ys = (ys ~ '[])
-  SameShapeAs (x ': xs) ys =
-    (ys ~ (Head ys ': Tail ys), SameShapeAs xs (Tail ys))
+  SameShapeAs (x ': xs) ys = (ys ~ (Head ys ': Tail ys))
 
 -- | Utility function to compute the head of a type-level list.
 --
@@ -219,7 +225,7 @@
 class Coercible (f x) (g y) => LiftedCoercible f g x y
 instance Coercible (f x) (g y) => LiftedCoercible f g x y
 
--- | Require a constraint for pointwise for every pair of
+-- | Require a constraint pointwise for every pair of
 -- elements from two lists of lists.
 --
 --
@@ -230,7 +236,7 @@
 --
 -- Note that the result of the composition must be a constraint,
 -- and therefore, in @'Compose' f g@, the kind of @f@ is @k -> 'Constraint'@.
--- The kind of @g@, however, is @l -> k@ and can thus be an normal
+-- The kind of @g@, however, is @l -> k@ and can thus be a normal
 -- type constructor.
 --
 -- A typical use case is in connection with 'All' on an 'Data.SOP.NP' or an
@@ -278,4 +284,3 @@
 -- on whether the argument is indexed by a list or a list of lists.
 --
 type family SListIN (h :: (k -> Type) -> (l -> Type)) :: l -> Constraint
-
diff --git a/src/Data/SOP/NP.hs b/src/Data/SOP/NP.hs
--- a/src/Data/SOP/NP.hs
+++ b/src/Data/SOP/NP.hs
@@ -483,7 +483,7 @@
 {-# DEPRECATED hcliftA2' "Use 'hcliftA2' or 'hczipWith' instead." #-}
 hcliftA2' :: (All2 c xss, Prod h ~ NP, HAp h) => proxy c -> (forall xs. All c xs => f xs -> f' xs -> f'' xs)            -> Prod h f xss                  -> h f'  xss -> h f''  xss
 
--- | Like 'hcliftA'', but for ternay functions.
+-- | Like 'hcliftA'', but for ternary functions.
 {-# DEPRECATED hcliftA3' "Use 'hcliftA3' or 'hczipWith3' instead." #-}
 hcliftA3' :: (All2 c xss, Prod h ~ NP, HAp h) => proxy c -> (forall xs. All c xs => f xs -> f' xs -> f'' xs -> f''' xs) -> Prod h f xss -> Prod h f' xss -> h f'' xss -> h f''' xss
 
diff --git a/src/Data/SOP/NS.hs b/src/Data/SOP/NS.hs
--- a/src/Data/SOP/NS.hs
+++ b/src/Data/SOP/NS.hs
@@ -24,6 +24,9 @@
   , unZ
   , index_NS
   , index_SOP
+  , Ejection
+  , ejections
+  , shiftEjection
     -- * Application
   , ap_NS
   , ap_SOP
@@ -156,6 +159,35 @@
     rnf (Z x)  = rnf x
     rnf (S xs) = rnf xs
 
+-- | The type of ejections from an n-ary sum.
+--
+-- An ejection is the pattern matching function for one part of the n-ary sum.
+--
+-- It is the opposite of an 'Injection'.
+--
+-- @since 0.5.0.0
+--
+type Ejection (f :: k -> Type) (xs :: [k]) = K (NS f xs) -.-> Maybe :.: f
+
+-- | Compute all ejections from an n-ary sum.
+--
+-- Each element of the resulting product contains one of the ejections.
+--
+-- @since 0.5.0.0
+--
+ejections :: forall xs f . SListI xs => NP (Ejection f xs) xs
+ejections = case sList :: SList xs of
+  SNil  -> Nil
+  SCons ->
+    fn (Comp . (\ns -> case ns of Z fx -> Just fx; S _ -> Nothing) . unK) :*
+    liftA_NP shiftEjection ejections
+
+-- |
+-- @since 0.5.0.0
+--
+shiftEjection :: forall f x xs a . Ejection f xs a -> Ejection f (x ': xs) a
+shiftEjection (Fn f) = Fn $ (\ns -> case ns of Z _ -> Comp Nothing; S s -> f (K s)) . unK
+
 -- | Extract the payload from a unary sum.
 --
 -- For larger sums, this function would be partial, so it is only
@@ -205,7 +237,7 @@
 -- of both the (outer) sum and all the (inner) products, as well as
 -- the types of all the elements of the inner products.
 --
--- An @'SOP' 'I'@ reflects the structure of a normal Haskell datatype.
+-- A @'SOP' 'I'@ reflects the structure of a normal Haskell datatype.
 -- The sum structure represents the choice between the different
 -- constructors, the product structure represents the arguments of
 -- each constructor.
diff --git a/src/Data/SOP/Sing.hs b/src/Data/SOP/Sing.hs
--- a/src/Data/SOP/Sing.hs
+++ b/src/Data/SOP/Sing.hs
@@ -81,7 +81,7 @@
 
 -- * Shape of type-level lists
 
--- | Occassionally it is useful to have an explicit, term-level, representation
+-- | Occasionally it is useful to have an explicit, term-level, representation
 -- of type-level lists (esp because of https://ghc.haskell.org/trac/ghc/ticket/9108 )
 --
 data Shape :: [k] -> Type where
@@ -108,4 +108,3 @@
     lengthShape :: forall xs'. Shape xs' -> Int
     lengthShape ShapeNil      = 0
     lengthShape (ShapeCons s) = 1 + lengthShape s
-
