diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+# 0.5.3
+
+* Fix `tanA` and `tanhA`. [#96](https://github.com/lehins/massiv/pull/96)
+* Relax argument of `snoc` and `cons` constraint to `Load` vectors
+* Improve `unsnocM` and `unconsM` by switching to `unsafeLinearSlice`, instead of delaying
+  the array.
+
 # 0.5.2
 
 * Addition of `lowerTriangular` and `upperTriangular`
diff --git a/Setup.hs b/Setup.hs
--- a/Setup.hs
+++ b/Setup.hs
@@ -1,33 +1,4 @@
-{-# LANGUAGE CPP #-}
-{-# OPTIONS_GHC -Wall #-}
-module Main (main) where
-
-#ifndef MIN_VERSION_cabal_doctest
-#define MIN_VERSION_cabal_doctest(x,y,z) 0
-#endif
-
-#if MIN_VERSION_cabal_doctest(1,0,0)
-
-import Distribution.Extra.Doctest ( defaultMainWithDoctests )
-main :: IO ()
-main = defaultMainWithDoctests "doctests"
-
-#else
-
-#ifdef MIN_VERSION_Cabal
--- If the macro is defined, we have new cabal-install,
--- but for some reason we don't have cabal-doctest in package-db
---
--- Probably we are running cabal sdist, when otherwise using new-build
--- workflow
-#warning You are configuring this package without cabal-doctest installed. \
-         The doctests test-suite will not work as a result. \
-         To fix this, install cabal-doctest before configuring.
-#endif
-
 import Distribution.Simple
 
 main :: IO ()
 main = defaultMain
-
-#endif
diff --git a/massiv.cabal b/massiv.cabal
--- a/massiv.cabal
+++ b/massiv.cabal
@@ -1,5 +1,5 @@
 name:                massiv
-version:             0.5.2.0
+version:             0.5.3.0
 synopsis:            Massiv (Массив) is an Array Library.
 description:         Multi-dimensional Arrays with fusion, stencils and parallel computation.
 homepage:            https://github.com/lehins/massiv
@@ -9,7 +9,7 @@
 maintainer:          alexey@kuleshevi.ch
 copyright:           2018-2020 Alexey Kuleshevich
 category:            Data, Data Structures, Parallelism
-build-type:          Custom
+build-type:          Simple
 extra-source-files:  README.md
                    , CHANGELOG.md
 cabal-version:       >=1.10
@@ -25,12 +25,6 @@
                significant performance penalty
   default: False
   manual: True
-
-custom-setup
-  setup-depends:
-      base
-    , Cabal
-    , cabal-doctest >=1.0.6
 
 library
   hs-source-dirs:      src
diff --git a/src/Data/Massiv/Array/Delayed/Push.hs b/src/Data/Massiv/Array/Delayed/Push.hs
--- a/src/Data/Massiv/Array/Delayed/Push.hs
+++ b/src/Data/Massiv/Array/Delayed/Push.hs
@@ -267,7 +267,8 @@
 toLoadArray arr =
   DLArray (getComp arr) (size arr) Nothing $ \scheduler startAt dlWrite ->
     loadArrayM scheduler arr (dlWrite . (+ startAt))
-{-# INLINE toLoadArray #-}
+{-# INLINE[1] toLoadArray #-}
+{-# RULES "toLoadArray/id" toLoadArray = id #-}
 
 -- | Convert an array that can be loaded with stride into `DL` representation.
 --
diff --git a/src/Data/Massiv/Array/Delayed/Stream.hs b/src/Data/Massiv/Array/Delayed/Stream.hs
--- a/src/Data/Massiv/Array/Delayed/Stream.hs
+++ b/src/Data/Massiv/Array/Delayed/Stream.hs
@@ -149,7 +149,8 @@
 -- @since 0.4.1
 toStreamArray :: Source r ix e => Array r ix e -> Array DS Ix1 e
 toStreamArray = DSArray . S.steps
-{-# INLINE toStreamArray #-}
+{-# INLINE[1] toStreamArray #-}
+{-# RULES "toStreamArray/id" toStreamArray = id #-}
 
 -- | /O(1)/ - Convert an array into monadic `Steps`
 --
diff --git a/src/Data/Massiv/Array/Manifest/Internal.hs b/src/Data/Massiv/Array/Manifest/Internal.hs
--- a/src/Data/Massiv/Array/Manifest/Internal.hs
+++ b/src/Data/Massiv/Array/Manifest/Internal.hs
@@ -366,8 +366,8 @@
 
 -- | Same as `compute`, but with `Stride`.
 --
--- /O(n div k)/ - Where @n@ is numer of elements in the source array and @k@ is number of elemts in
--- the stride.
+-- /O(n div k)/ - Where @n@ is numer of elements in the source array and @k@ is number of
+-- elements in the stride.
 --
 -- @since 0.3.0
 computeWithStride ::
diff --git a/src/Data/Massiv/Array/Numeric.hs b/src/Data/Massiv/Array/Numeric.hs
--- a/src/Data/Massiv/Array/Numeric.hs
+++ b/src/Data/Massiv/Array/Numeric.hs
@@ -445,7 +445,7 @@
 {-# INLINE cosA #-}
 
 tanA :: (Index ix, NumericFloat r e) => Array r ix e -> Array r ix e
-tanA = unsafeLiftArray cos
+tanA = unsafeLiftArray tan
 {-# INLINE tanA #-}
 
 asinA :: (Index ix, NumericFloat r e) => Array r ix e -> Array r ix e
@@ -465,7 +465,7 @@
 {-# INLINE sinhA #-}
 
 tanhA :: (Index ix, NumericFloat r e) => Array r ix e -> Array r ix e
-tanhA = unsafeLiftArray cos
+tanhA = unsafeLiftArray tanh
 {-# INLINE tanhA #-}
 
 coshA :: (Index ix, NumericFloat r e) => Array r ix e -> Array r ix e
diff --git a/src/Data/Massiv/Core/Common.hs b/src/Data/Massiv/Core/Common.hs
--- a/src/Data/Massiv/Core/Common.hs
+++ b/src/Data/Massiv/Core/Common.hs
@@ -105,10 +105,11 @@
 
 #include "massiv.h"
 
--- | The array family. Representations @r@ describes how data is arranged or computed. All arrays
--- have a common property that each index @ix@ always maps to the same unique element, even if that
--- element does not exist in memory and has to be computed upon lookup. Data is always arranged in a
--- nested fashion, depth of which is controlled by @`Rank` ix@.
+-- | The array family. Representations @r@ describe how data is arranged or computed. All
+-- arrays have a common property that each index @ix@ always maps to the same unique
+-- element, even if that element does not yet exist in memory and the arry has to be
+-- computed in order to get access to that element. Data is always arranged in a nested
+-- row-major fashion, depth of which is controlled by @`Rank` ix@.
 data family Array r ix e :: *
 
 -- | Type synonym for a single dimension array, or simply a flat vector.
diff --git a/src/Data/Massiv/Vector.hs b/src/Data/Massiv/Vector.hs
--- a/src/Data/Massiv/Vector.hs
+++ b/src/Data/Massiv/Vector.hs
@@ -505,22 +505,19 @@
 -- ==== __Examples__
 --
 -- >>> unconsM (fromList Seq [1,2,3] :: Array P Ix1 Int)
--- (1,Array D Seq (Sz1 2)
+-- (1,Array P Seq (Sz1 2)
 --   [ 2, 3 ])
 --
 -- /__Similar__/:
 --
--- [@Data.List.`Data.List.uncons`@] Same concept, except restricted to `Maybe` instead of
+-- [@Data.List.`Data.List.uncons`@] Same concept, except it is restricted to `Maybe` instead of
 -- the more general `MonadThrow`
 --
 -- @since 0.3.0
-unconsM :: (MonadThrow m, Source r Ix1 e) => Vector r e -> m (e, Vector D e)
+unconsM :: (MonadThrow m, Source r Ix1 e) => Vector r e -> m (e, Vector r e)
 unconsM arr
   | 0 == totalElem sz = throwM $ SizeEmptyException sz
-  | otherwise =
-    pure
-      ( unsafeLinearIndex arr 0
-      , makeArray (getComp arr) (SafeSz (unSz sz - 1)) (\ !i -> unsafeLinearIndex arr (i + 1)))
+  | otherwise = pure (unsafeLinearIndex arr 0, unsafeLinearSlice 1 (SafeSz (unSz sz - 1)) arr)
   where
     !sz = size arr
 {-# INLINE unconsM #-}
@@ -535,15 +532,14 @@
 -- ==== __Examples__
 --
 -- >>> unsnocM (fromList Seq [1,2,3] :: Array P Ix1 Int)
--- (Array D Seq (Sz1 2)
+-- (Array P Seq (Sz1 2)
 --   [ 1, 2 ],3)
 --
 -- @since 0.3.0
-unsnocM :: (MonadThrow m, Source r Ix1 e) => Vector r e -> m (Vector D e, e)
+unsnocM :: (MonadThrow m, Source r Ix1 e) => Vector r e -> m (Vector r e, e)
 unsnocM arr
-  | k < 0 = throwM $ SizeEmptyException sz
-  | otherwise =
-    pure (makeArray (getComp arr) (SafeSz k) (unsafeLinearIndex arr), unsafeLinearIndex arr k)
+  | 0 == totalElem sz = throwM $ SizeEmptyException sz
+  | otherwise = pure (unsafeLinearSlice 0 (SafeSz k) arr, unsafeLinearIndex arr k)
   where
     !sz = size arr
     !k = unSz sz - 1
@@ -960,29 +956,30 @@
 -- | /O(1)/ - Add an element to the vector from the left side
 --
 -- @since 0.3.0
-cons :: e -> Vector DL e -> Vector DL e
-cons e arr =
-  arr
-    { dlSize = SafeSz (1 + unSz (dlSize arr))
-    , dlLoad =
-        \scheduler startAt uWrite ->
-          uWrite startAt e >> dlLoad arr scheduler (startAt + 1) uWrite
-    }
+cons :: Load r Ix1 e => e -> Vector r e -> Vector DL e
+cons e v =
+  let dv = toLoadArray v
+   in dv
+        { dlSize = SafeSz (1 + unSz (dlSize dv))
+        , dlLoad =
+            \scheduler startAt uWrite ->
+              uWrite startAt e >> dlLoad dv scheduler (startAt + 1) uWrite
+        }
 {-# INLINE cons #-}
 
-
 -- | /O(1)/ - Add an element to the vector from the right side
 --
 -- @since 0.3.0
-snoc :: Vector DL e -> e -> Vector DL e
-snoc arr e =
-  arr
-    { dlSize = SafeSz (1 + k)
-    , dlLoad =
-        \scheduler startAt uWrite -> dlLoad arr scheduler startAt uWrite >> uWrite (k + startAt) e
-    }
-  where
-    !k = unSz (size arr)
+snoc :: Load r Ix1 e => Vector r e -> e -> Vector DL e
+snoc v e =
+  let dv = toLoadArray v
+      !k = unSz (size dv)
+   in dv
+        { dlSize = SafeSz (1 + k)
+        , dlLoad =
+            \scheduler startAt uWrite ->
+              dlLoad dv scheduler startAt uWrite >> uWrite (k + startAt) e
+        }
 {-# INLINE snoc #-}
 
 
diff --git a/src/Data/Massiv/Vector/Stream.hs b/src/Data/Massiv/Vector/Stream.hs
--- a/src/Data/Massiv/Vector/Stream.hs
+++ b/src/Data/Massiv/Vector/Stream.hs
@@ -391,10 +391,9 @@
 cons e (Steps str k) = Steps (S.cons e str) (k + 1)
 {-# INLINE cons #-}
 
+-- | First element of the `Steps` or `Nothing` if empty
 uncons :: Monad m => Steps m e -> m (Maybe (e, Steps m e))
-uncons sts@(Steps str _) = do
-  mx <- str S.!? 0
-  pure $ fmap (, drop 1 sts) mx
+uncons sts = (\mx -> (\x -> (x, drop 1 sts)) <$> mx) <$> headMaybe sts
 {-# INLINE uncons #-}
 
 snoc :: Monad m => Steps m e -> e -> Steps m e
diff --git a/tests/doctests.hs b/tests/doctests.hs
--- a/tests/doctests.hs
+++ b/tests/doctests.hs
@@ -1,12 +1,6 @@
 module Main where
 
-import Build_doctests (flags, pkgs, module_sources)
-import Data.Foldable (traverse_)
 import Test.DocTest (doctest)
 
 main :: IO ()
-main = do
-    traverse_ putStrLn args
-    doctest args
-  where
-    args = flags ++ pkgs ++ module_sources
+main = doctest ["src"]
