diff --git a/ftree.cabal b/ftree.cabal
--- a/ftree.cabal
+++ b/ftree.cabal
@@ -1,5 +1,5 @@
 Name:                ftree
-Version:             0.1.3
+Version:             0.1.5
 Cabal-Version:       >= 1.6
 Synopsis:            Depth-typed functor-based trees, both top-down and bottom-up
 Category:            Data
@@ -25,4 +25,4 @@
   Exposed-Modules:     
                        Data.FTree.TopDown
                        Data.FTree.BottomUp
-  ghc-options:         -Wall
+  ghc-options:         -Wall -O2
diff --git a/src/Data/FTree/BottomUp.hs b/src/Data/FTree/BottomUp.hs
--- a/src/Data/FTree/BottomUp.hs
+++ b/src/Data/FTree/BottomUp.hs
@@ -1,6 +1,7 @@
 {-# LANGUAGE GADTs, KindSignatures, TypeOperators, Rank2Types, DataKinds #-}
 {-# LANGUAGE TypeSynonymInstances #-}
 {-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE CPP #-}
 {-# OPTIONS_GHC -Wall #-}
 
 ----------------------------------------------------------------------
@@ -16,7 +17,9 @@
 -- See <http://conal.net/blog/posts/a-trie-for-length-typed-vectors/>.
 ----------------------------------------------------------------------
 
-module Data.FTree.BottomUp (T(..),(:^),unL,unB,foldT,inT,inT2,inL,inB,inL2,inB2) where
+module Data.FTree.BottomUp
+  ( T(..),(:^),unL,unB,foldT,inT,inT2,inL,inB,inL2,inB2
+  ) where
 
 -- TODO: explicit exports
 
@@ -25,7 +28,8 @@
 import Control.Applicative (Applicative(..),liftA2,(<$>))
 import Data.Foldable (Foldable(..),and)
 import Data.Traversable (Traversable(..))
-import Data.Monoid (Monoid(..))
+--import Data.Monoid (Monoid(..))
+import qualified Data.Semigroup as Sem
 
 import TypeUnary.Nat
 
@@ -67,35 +71,39 @@
 
 -- Operate inside the representation of `f :^ n`:
 
+-- | Operate inside the representation of `f :^ n` to make another,
+-- preserving depth.
 inT :: (a -> b)
     -> (forall n. IsNat n => (f :^ n) (f a) -> (f :^ n) (f b))
-    -> (forall n. (f :^ n) a -> (f :^ n) b)
+    -> (forall n.            (f :^ n)    a  -> (f :^ n) b)
 inT l _ (L a ) = (L (l a ))
 inT _ b (B as) = (B (b as))
 
+-- | Operate inside the representation of two `f :^ n` to make another,
+-- preserving depth.
 inT2 :: (a -> b -> c)
      -> (forall n. IsNat n => (f :^ n) (f a) -> (f :^ n) (f b) -> (f :^ n) (f c))
      -> (forall n. (f :^ n) a -> (f :^ n) b -> (f :^ n) c)
 inT2 l _ (L a ) (L b ) = L (l a  b )
 inT2 _ b (B as) (B bs) = B (b as bs)
-inT2 _ _ _ _ = error "inT2: unhandled case"  -- Possible??
 
+
 -- Similar to `inT`, but useful when we can know whether a `L` or a `B`:
 
 inL :: (a -> b)
-        -> ((f :^ Z) a -> (f :^ Z) b)
+    -> ((f :^ Z) a -> (f :^ Z) b)
 inL h (L a ) = L (h a )
 
 inB :: ((f :^ n) (f a) -> (f :^ n) (f b))
-        -> ((f :^ (S n)) a -> (f :^ (S n)) b)
+    -> ((f :^ (S n)) a -> (f :^ (S n)) b)
 inB h (B as) = B (h as)
 
 inL2 :: (a -> b -> c)
-         -> ((f :^ Z) a -> (f :^ Z) b -> (f :^ Z) c)
+     -> ((f :^ Z) a -> (f :^ Z) b -> (f :^ Z) c)
 inL2 h (L a ) (L b ) = L (h a  b )
 
 inB2 :: ((f :^ n) (f a) -> (f :^ n) (f b) -> (f :^ n) (f c))
-         -> ((f :^ (S n)) a -> (f :^ (S n)) b -> (f :^ (S n)) c)
+     -> ((f :^ (S n)) a -> (f :^ (S n)) b -> (f :^ (S n)) c)
 inB2 h (B as) (B bs) = B (h as bs)
 
 
@@ -144,7 +152,7 @@
 
 instance Traversable f => Traversable (f :^ n) where
   sequenceA (L qa) = L <$> qa
-  sequenceA (B as) = fmap B . sequenceA . fmap sequenceA $ as
+  sequenceA (B as) = B <$> traverse sequenceA as
 
 -- i.e.,
 
@@ -154,9 +162,14 @@
 
 -- We can use the `Applicative` instance in standard way to get a `Monoid` instance:
 
+instance (IsNat n, Applicative f, Sem.Semigroup m) => Sem.Semigroup (( f :^ n) m) where
+  (<>) = liftA2 (Sem.<>)
+
 instance (IsNat n, Applicative f, Monoid m) => Monoid ((f :^ n) m) where
   mempty  = pure mempty
+#if !(MIN_VERSION_base(4,11,0))
   mappend = liftA2 mappend
+#endif
 
 -- (To follow the general pattern exactly, replace the first two constraints with `Applicative (f :^ n)` and add `FlexibleContexts` to the module's `LANGUAGE` pragma.)
 
diff --git a/src/Data/FTree/TopDown.hs b/src/Data/FTree/TopDown.hs
--- a/src/Data/FTree/TopDown.hs
+++ b/src/Data/FTree/TopDown.hs
@@ -1,6 +1,7 @@
 {-# LANGUAGE GADTs, KindSignatures, TypeOperators, Rank2Types, DataKinds #-}
 {-# LANGUAGE TypeSynonymInstances #-}
 {-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE CPP #-}
 {-# OPTIONS_GHC -Wall #-}
 
 ----------------------------------------------------------------------
@@ -16,7 +17,9 @@
 -- See <http://conal.net/blog/posts/a-trie-for-length-typed-vectors/>.
 ----------------------------------------------------------------------
 
-module Data.FTree.TopDown (T(..),(:^),unL,unB,foldT,inT,inT2,inL,inB,inL2,inB2) where
+module Data.FTree.TopDown
+  ( T(..),(:^),unL,unB,foldT,inT,inT2,inL,inB,inL2,inB2
+  ) where
 
 -- TODO: explicit exports
 
@@ -25,7 +28,7 @@
 import Control.Applicative (Applicative(..),liftA2,(<$>))
 import Data.Foldable (Foldable(..),and)
 import Data.Traversable (Traversable(..))
-import Data.Monoid (Monoid(..))
+import qualified Data.Semigroup as Sem
 
 import TypeUnary.Nat
 
@@ -65,20 +68,21 @@
    fo (L a)  = l a
    fo (B ts) = b (fo <$> ts)
 
--- Operate inside the representation of `f :^ n`:
-
+-- | Operate inside the representation of `f :^ n` to make another,
+-- preserving depth.
 inT :: (a -> b)
     -> (forall n. IsNat n => f ((f :^ n) a) -> f ((f :^ n) b))
     -> (forall n. (f :^ n) a -> (f :^ n) b)
 inT l _ (L a ) = (L (l a ))
 inT _ b (B as) = (B (b as))
 
+-- | Operate inside the representation of two `f :^ n` to make another,
+-- preserving depth.
 inT2 :: (a -> b -> c)
      -> (forall n. IsNat n => f ((f :^ n) a) -> f ((f :^ n) b) -> f ((f :^ n) c))
-     -> (forall n. (f :^ n) a -> (f :^ n) b -> (f :^ n) c)
+     -> (forall n.               (f :^ n) a  ->    (f :^ n) b  ->    (f :^ n) c)
 inT2 l _ (L a ) (L b ) = L (l a  b )
 inT2 _ b (B as) (B bs) = B (b as bs)
-inT2 _ _ _ _ = error "inT2: unhandled case"  -- Possible??
 
 -- Similar to `inT`, but useful when we can know whether a `L` or a `B`:
 
@@ -143,7 +147,7 @@
 
 instance Traversable f => Traversable (f :^ n) where
   sequenceA (L qa) = L <$> qa
-  sequenceA (B as) = fmap B . sequenceA . fmap sequenceA $ as
+  sequenceA (B as) = B <$> traverse sequenceA as
 
 -- i.e.,
 
@@ -153,9 +157,14 @@
 
 -- We can use the `Applicative` instance in standard way to get a `Monoid` instance:
 
+instance (IsNat n, Applicative f, Sem.Semigroup m) => Sem.Semigroup ((f :^ n) m) where
+  (<>) = liftA2 (Sem.<>)
+
 instance (IsNat n, Applicative f, Monoid m) => Monoid ((f :^ n) m) where
   mempty  = pure mempty
+#if !(MIN_VERSION_base(4,11,0))
   mappend = liftA2 mappend
+#endif
 
 -- (To follow the general pattern exactly, replace the first two constraints with `Applicative (f :^ n)` and add `FlexibleContexts` to the module's `LANGUAGE` pragma.)
 
