diff --git a/Data/Functor/Representable/Trie.hs b/Data/Functor/Representable/Trie.hs
--- a/Data/Functor/Representable/Trie.hs
+++ b/Data/Functor/Representable/Trie.hs
@@ -20,52 +20,76 @@
   , inTrie, inTrie2, inTrie3
   -- * Workarounds for current GHC limitations
   , trie, untrie
-  , coerceKey, uncoerceKey
+  , (:->:)(..)
+  , Entry(..)
+  , runTrie
   ) where
 
+import Control.Applicative
+import Control.Arrow
+import Control.Comonad
+import Control.Monad.Reader
 import Control.Monad.Representable
+import Data.Bits
+import Data.Distributive
 import Data.Eq.Type
+import Data.Foldable
+import Data.Function (on)
+import Data.Functor.Adjunction
+import Data.Functor.Bind
 import Data.Functor.Identity
 import Data.Functor.Product
+import Data.Functor.Representable
 import Data.Functor.Representable.Trie.Bool
+import Data.Functor.Representable.Trie.Either
 import Data.Functor.Representable.Trie.List
 import Data.Key
-import Prelude hiding (lookup)
+import Data.Key
+import Data.Monoid as Monoid
+import Data.Semigroup.Foldable
+import Data.Semigroup.Traversable
+import Data.Semigroupoid
+import Data.Sequence (Seq, (<|))
+import qualified Data.Sequence as Seq
+import Data.Map (Map)
+import qualified Data.Map as Map
+import Data.IntMap (IntMap)
+import qualified Data.IntMap as IntMap
+import Data.Traversable
+import Prelude hiding (lookup, foldr)
 
--- class (TraversableWithKey1 (Trie a), Representable (Trie a), Key (Trie a) ~ a) => HasTrie a where
-class (TraversableWithKey1 (Trie a), Representable (Trie a)) => HasTrie a where
-  type Trie a :: * -> *
-  -- | Ideally we would have the constraint @Key (Trie a) ~ a@ as a class constraint. 
-  -- We are forced to approximate this using an explicit equality witness until GHC implements this feature.
-  keyRefl :: a := Key (Trie a)
+class (TraversableWithKey1 (BaseTrie a), Representable (BaseTrie a)) => HasTrie a where
+  type BaseTrie a :: * -> *
+  -- projectKey . embedKey = id
+  embedKey   :: a -> Key (BaseTrie a)
+  projectKey :: Key (BaseTrie a) -> a
 
-coerceKey :: HasTrie a => a -> Key (Trie a)
-coerceKey = go keyRefl where
-  go :: HasTrie a => (a := Key (Trie a)) -> a -> Key (Trie a)
-  go Refl = id
+data a :->: b where
+  Trie :: HasTrie a => BaseTrie a b -> a :->: b
 
-uncoerceKey :: HasTrie a => Key (Trie a) -> a
-uncoerceKey = go keyRefl where
-  go :: HasTrie a => (a := Key (Trie a)) -> Key (Trie a) -> a
-  go Refl = id
+type instance Key ((:->:) a) = a
 
+data Entry a b = Entry a b
+
+-- * Combinators
+
+runTrie :: (a :->: b) -> BaseTrie a b
+runTrie (Trie f) = f
+
 -- Matt Hellige's notation for @argument f . result g@.
 -- <http://matt.immute.net/content/pointless-fun>
 (~>) :: (a' -> a) -> (b -> b') -> (a -> b) -> a' -> b'
 g ~> f = (f .) . (. g)
 
-untrie :: HasTrie t => Trie t a -> t -> a
-untrie = go keyRefl where
-  go :: HasTrie t => (t := Key (Trie t)) -> Trie t a -> t -> a
-  go Refl = index
+untrie :: (t :->: a) -> t -> a
+untrie = index
 
-trie :: HasTrie t => (t -> a) -> Trie t a
-trie = go keyRefl where
-  go :: HasTrie t => (t := Key (Trie t)) -> (t -> a) -> Trie t a
-  go Refl = tabulate
+trie :: HasTrie t => (t -> a) -> (t :->: a)
+trie = tabulate
 
 {-# RULES
 "trie/untrie" forall t. trie (untrie t) = t
+"embedKey/projectKey" forall t. projectKey (embedKey t) = t
  #-}
 
 memo :: HasTrie t => (t -> a) -> t -> a
@@ -89,47 +113,229 @@
 inTrie 
   :: (HasTrie a, HasTrie c) 
   => ((a -> b) -> c -> d)
-  -> Trie a b -> Trie c d
+  -> (a :->: b) -> c :->: d
 inTrie = untrie ~> trie
 
 -- | Apply a binary function inside of a tabulate
 inTrie2 
   :: (HasTrie a, HasTrie c, HasTrie e) 
   => ((a -> b) -> (c -> d) -> e -> f)
-  -> Trie a b -> Trie c d -> Trie e f
+  -> (a :->: b) -> (c :->: d) -> e :->: f
 inTrie2 = untrie ~> inTrie
 
 -- | Apply a ternary function inside of a tabulate
 inTrie3 
   :: (HasTrie a, HasTrie c, HasTrie e, HasTrie g) 
   => ((a -> b) -> (c -> d) -> (e -> f) -> g -> h)
-  -> Trie a b -> Trie c d -> Trie e f -> Trie g h
+  -> (a :->: b) -> (c :->: d) -> (e :->: f) -> g :->: h
 inTrie3 = untrie ~> inTrie2
 
+-- * Implementation details
+
+instance Functor (Entry a) where
+  fmap f (Entry a b) = Entry a (f b)
+
+instance Indexable ((:->:)e) where
+  index (Trie f) = index f . embedKey
+
+instance HasTrie e => Distributive ((:->:) e) where
+  distribute = distributeRep
+
+instance HasTrie e => Representable ((:->:) e) where
+  tabulate f = Trie $ tabulate (f . projectKey)
+
+instance HasTrie e => Adjunction (Entry e) ((:->:) e) where
+  unit = mapWithKey Entry . pure
+  counit (Entry a t) = index t a
+
+instance Functor ((:->:) a) where
+  fmap f (Trie g) = Trie (fmap f g)
+
+instance Keyed ((:->:) a) where
+  mapWithKey f (Trie a) = Trie (mapWithKey (f . projectKey) a)
+
+instance Foldable ((:->:) a) where
+  foldMap f (Trie a) = foldMap f a
+
+instance FoldableWithKey ((:->:) a) where
+  foldMapWithKey f (Trie a) = foldMapWithKey (f . projectKey) a
+
+instance Traversable ((:->:) a) where
+  traverse f (Trie a) = Trie <$> traverse f a
+
+instance TraversableWithKey ((:->:) a) where
+  traverseWithKey f (Trie a) = Trie <$> traverseWithKey (f . projectKey) a
+
+instance Foldable1 ((:->:) a) where
+  foldMap1 f (Trie a) = foldMap1 f a
+
+instance FoldableWithKey1 ((:->:) a) where
+  foldMapWithKey1 f (Trie a) = foldMapWithKey1 (f . projectKey) a
+
+instance Traversable1 ((:->:) a) where
+  traverse1 f (Trie a) = Trie <$> traverse1 f a
+
+instance TraversableWithKey1 ((:->:) a) where
+  traverseWithKey1 f (Trie a) = Trie <$> traverseWithKey1 (f . projectKey) a
+
+instance Eq b => Eq (a :->: b) where
+  (==) = (==) `on` toList
+
+instance Ord b => Ord (a :->: b) where
+  compare = compare `on` toList
+
+instance (Show a, Show b) => Show (a :->: b) where 
+  showsPrec d t = showsPrec d (toKeyedList t)
+
+instance Apply ((:->:) a) where
+  Trie f <.> Trie g = Trie (f <.> g)
+  a <. _ = a
+  _ .> b = b
+
+instance Semigroupoid (:->:) where
+  o (Trie f) = fmap (index f . embedKey)
+
+-- instance HasTrie a => Ob (:->:) a where semiid = Trie return
+
+instance HasTrie a => Applicative ((:->:) a) where
+  pure a = Trie (pure a)
+  Trie f <*> Trie g = Trie (f <*> g)
+  a <* _ = a
+  _ *> b = b
+
+instance Bind ((:->:) a) where
+  Trie m >>- f = Trie (tabulate (\a -> index (runTrie (f (index m a))) a))
+  
+instance HasTrie a => Monad ((:->:) a) where
+  return a = Trie (pureRep a)
+  (>>=) = (>>-)
+  _ >> m = m
+
+instance HasTrie a => MonadReader a ((:->:) a) where
+  ask = askRep
+  local = localRep
+
+-- TODO: remove dependency on HasTrie in these: 
+
+instance (HasTrie m, Semigroup m, Monoid m) => Comonad ((:->:) m) where
+  extract = flip index mempty
+
+instance (HasTrie m, Semigroup m) => Extend ((:->:) m) where
+  duplicate = duplicateRep
+
 -- * Instances
 
 instance HasTrie () where
-  type Trie () = Identity
-  keyRefl = Refl
+  type BaseTrie () = Identity
+  embedKey = id
+  projectKey = id
 
 instance HasTrie Bool where
-  type Trie Bool = BoolTrie
-  keyRefl = Refl
+  type BaseTrie Bool = BoolTrie
+  embedKey = id
+  projectKey = id
 
+instance HasTrie Any where
+  type BaseTrie Any = BoolTrie
+  embedKey = getAny
+  projectKey = Any
+
+instance HasTrie a => HasTrie (Dual a) where
+  type BaseTrie (Dual a) = BaseTrie a
+  embedKey = embedKey . getDual
+  projectKey = Dual . projectKey 
+
+instance HasTrie a => HasTrie (Sum a) where
+  type BaseTrie (Sum a) = BaseTrie a
+  embedKey = embedKey . getSum
+  projectKey = Sum . projectKey 
+
+instance HasTrie a => HasTrie (Monoid.Product a) where
+  type BaseTrie (Monoid.Product a) = BaseTrie a
+  embedKey = embedKey . Monoid.getProduct
+  projectKey = Monoid.Product . projectKey 
+
 instance (HasTrie a, HasTrie b) => HasTrie (a, b) where
-  type Trie (a, b) = RepT (Trie a) (Trie b)
-  keyRefl = go keyRefl keyRefl where
-    go :: (a := Key (Trie a)) -> (b := Key (Trie b)) -> (a, b) := Key (Trie (a,b))
-    go Refl Refl = Refl
+  type BaseTrie (a, b) = RepT (BaseTrie a) (BaseTrie b)
+  embedKey = embedKey *** embedKey
+  projectKey = projectKey *** projectKey
 
+instance (HasTrie a, HasTrie b) => HasTrie (Entry a b) where
+  type BaseTrie (Entry a b) = RepT (BaseTrie a) (BaseTrie b)
+  embedKey (Entry a b) = (embedKey a, embedKey b)
+  projectKey (a, b) = Entry (projectKey a) (projectKey b)
+
 instance (HasTrie a, HasTrie b) => HasTrie (Either a b) where
-  type Trie (Either a b) = Product (Trie a) (Trie b)
-  keyRefl = go keyRefl keyRefl where
-    go :: (a := Key (Trie a)) -> (b := Key (Trie b)) -> Either a b := Key (Trie (Either a b))
-    go Refl Refl = Refl
+  type BaseTrie (Either a b) = EitherTrie (BaseTrie a) (BaseTrie b)
+  embedKey = embedKey +++ embedKey
+  projectKey = projectKey +++ projectKey
 
+instance HasTrie a => HasTrie (Maybe a) where
+  type BaseTrie (Maybe a) = EitherTrie Identity (BaseTrie a)
+  embedKey   = maybe (Left ()) (Right . embedKey)
+  projectKey = either (const Nothing) (Just . projectKey)
+
 instance HasTrie a => HasTrie [a] where
-  type Trie [a] = ListTrie (Trie a)
-  keyRefl = go keyRefl where
-    go :: (a := Key (Trie a)) -> [a] := Key (Trie [a])
-    go Refl = Refl
+  type BaseTrie [a] = ListTrie (BaseTrie a)
+  embedKey = map embedKey
+  projectKey = map projectKey
+
+instance HasTrie a => HasTrie (Seq a) where
+  type BaseTrie (Seq a) = ListTrie (BaseTrie a)
+  embedKey = foldr ((:) . embedKey) []
+  projectKey = foldr ((<|) . projectKey) (Seq.empty)
+
+instance (HasTrie k, HasTrie v) => HasTrie (Map k v) where
+  type BaseTrie (Map k v) = ListTrie (BaseTrie (k, v))
+  embedKey = foldrWithKey (\k v t -> embedKey (k,v) : t) []
+  projectKey = Map.fromDistinctAscList . map projectKey
+
+instance (HasTrie v) => HasTrie (IntMap v) where
+  type BaseTrie (IntMap v) = ListTrie (BaseTrie (Int, v))
+  embedKey = foldrWithKey (\k v t -> embedKey (k,v) : t) []
+  projectKey = IntMap.fromDistinctAscList . map projectKey
+  
+  
+-- | Extract bits in little-endian order
+bits :: Bits t => t -> [Bool]
+bits 0 = []
+bits x = testBit x 0 : bits (shiftR x 1)
+
+-- | Convert boolean to 0 (False) or 1 (True)
+unbit :: Num t => Bool -> t
+unbit False = 0
+unbit True  = 1
+
+-- | Bit list to value
+unbits :: Bits t => [Bool] -> t
+unbits [] = 0
+unbits (x:xs) = unbit x .|. shiftL (unbits xs) 1
+
+unbitsZ :: (Bits n) => (Bool,[Bool]) -> n
+unbitsZ (positive,bs) = sig (unbits bs)
+ where
+   sig | positive  = id
+       | otherwise = negate
+
+bitsZ :: (Ord n, Bits n) => n -> (Bool,[Bool])
+bitsZ = (>= 0) &&& (bits . abs)
+
+instance HasTrie Int where
+  type BaseTrie Int = BaseTrie (Bool, [Bool])
+  embedKey = embedKey . bitsZ 
+  projectKey = unbitsZ . projectKey
+
+instance HasTrie Char where
+  type BaseTrie Char = BaseTrie Int
+  embedKey = embedKey . fromEnum
+  projectKey = toEnum . projectKey
+
+instance (HasTrie a, HasTrie b, HasTrie c) => HasTrie (a,b,c) where
+  type BaseTrie (a,b,c) = BaseTrie (a,(b,c))
+  embedKey (a,b,c) = embedKey (a,(b,c))
+  projectKey p = let (a,(b,c)) = projectKey p in (a,b,c)
+
+instance (HasTrie a, HasTrie b, HasTrie c, HasTrie d) => HasTrie (a,b,c,d) where
+  type BaseTrie (a,b,c,d) = BaseTrie ((a,b),(c,d))
+  embedKey (a,b,c,d) = embedKey ((a,b),(c,d))
+  projectKey p = let ((a,b),(c,d)) = projectKey p in (a,b,c,d)
diff --git a/Data/Semigroupoid/Trie.hs b/Data/Semigroupoid/Trie.hs
deleted file mode 100644
--- a/Data/Semigroupoid/Trie.hs
+++ /dev/null
@@ -1,138 +0,0 @@
-{-# LANGUAGE GADTs, TypeFamilies, TypeOperators, CPP, FlexibleContexts, FlexibleInstances, MultiParamTypeClasses #-}
-----------------------------------------------------------------------
--- |
--- Module      :  Data.Semigroupoid.Trie
--- Copyright   :  (c) Edward Kmett 2011
--- License     :  BSD3
--- 
--- Maintainer  :  ekmett@gmail.com
--- Stability   :  experimental
--- 
--- We may not be able to build a category out of tries, but we can
--- consruct a semigroupoid.
-----------------------------------------------------------------------
-
-module Data.Semigroupoid.Trie
-  ( (:->:)(..)
-  , Entry(..)
-  , runT
-  ) where
-
-import Control.Applicative
-import Control.Comonad
-import Control.Monad.Representable
-import Control.Monad.Reader
-import Control.Monad.Reader.Trie
-import Data.Distributive
-import Data.Function (on)
-import Data.Functor.Adjunction
-import Data.Functor.Representable
-import Data.Functor.Bind
-import Data.Foldable
-import Data.Key
-import Data.Monoid
-import Data.Traversable
-import Data.Semigroup.Traversable
-import Data.Semigroup.Foldable
-import Data.Semigroupoid
--- import Data.Semigroupoid.Ob
-
-data a :->: b where
-  T :: HasTrie a => Trie a b -> a :->: b
-
-type instance Key ((:->:) a) = a
-
-data Entry a b = Entry a b
-
-instance Functor (Entry a) where
-  fmap f (Entry a b) = Entry a (f b)
-
-runT :: (a :->: b) -> Trie a b
-runT (T f) = f
-
-instance Indexable ((:->:)e) where
-  index (T f) = untrie f
-
-instance HasTrie e => Distributive ((:->:)e) where
-  distribute = distributeRep
-
-instance HasTrie e => Representable ((:->:) e) where
-  tabulate f = T (trie f)
-
-instance HasTrie e => Adjunction (Entry e) ((:->:) e) where
-  unit = mapWithKey Entry . pure
-  counit (Entry a t) = index t a
-
-instance Functor ((:->:) a) where
-  fmap f (T g) = T (fmap f g)
-
-instance Keyed ((:->:) a) where
-  mapWithKey f (T a) = T (mapWithKey (f . uncoerceKey) a)
-
-instance Foldable ((:->:) a) where
-  foldMap f (T a) = foldMap f a
-
-instance FoldableWithKey ((:->:) a) where
-  foldMapWithKey f (T a) = foldMapWithKey (f . uncoerceKey) a
-
-instance Traversable ((:->:) a) where
-  traverse f (T a) = T <$> traverse f a
-
-instance TraversableWithKey ((:->:) a) where
-  traverseWithKey f (T a) = T <$> traverseWithKey (f . uncoerceKey) a
-
-instance Foldable1 ((:->:) a) where
-  foldMap1 f (T a) = foldMap1 f a
-
-instance FoldableWithKey1 ((:->:) a) where
-  foldMapWithKey1 f (T a) = foldMapWithKey1 (f . uncoerceKey) a
-
-instance Traversable1 ((:->:) a) where
-  traverse1 f (T a) = T <$> traverse1 f a
-
-instance TraversableWithKey1 ((:->:) a) where
-  traverseWithKey1 f (T a) = T <$> traverseWithKey1 (f . uncoerceKey) a
-
-instance Eq b => Eq (a :->: b) where
-  (==) = (==) `on` toList
-
-instance Ord b => Ord (a :->: b) where
-  compare = compare `on` toList
-
-instance (Show a, Show b) => Show (a :->: b) where 
-  showsPrec d t = showsPrec d (toKeyedList t)
-
-instance Apply ((:->:) a) where
-  T f <.> T g = T (f <.> g)
-  a <. _ = a
-  _ .> b = b
-
-instance Semigroupoid (:->:) where
-  o (T f) = fmap (index f . coerceKey)
-
--- instance HasTrie a => Ob (:->:) a where semiid = T return
-
-instance HasTrie a => Applicative ((:->:) a) where
-  pure a = T (pure a)
-  T f <*> T g = T (f <*> g)
-  a <* _ = a
-  _ *> b = b
-
-instance Bind ((:->:) a) where
-  T m >>- f = T (tabulate (\a -> index (runT (f (index m a))) a))
-  
-instance HasTrie a => Monad ((:->:) a) where
-  return a = T (pureRep a)
-  (>>=) = (>>-)
-  _ >> m = m
-
-instance HasTrie a => MonadReader a ((:->:) a) where
-  ask = askRep
-  local = localRep
-
-instance (HasTrie m, Semigroup m, Monoid m) => Comonad ((:->:) m) where
-  extract = flip index mempty
-
--- TODO: remove dependency on HasTrie
-instance (HasTrie m, Semigroup m) => Extend ((:->:) m) where
-  duplicate = duplicateRep
diff --git a/Data/Traversable/Fair.hs b/Data/Traversable/Fair.hs
new file mode 100644
--- /dev/null
+++ b/Data/Traversable/Fair.hs
@@ -0,0 +1,132 @@
+module Data.Traversable.Fair 
+  ( foldMapBoth
+  , traverseBoth
+  , foldMapWithKeyBoth
+  , traverseWithKeyBoth
+  , foldMapBoth1
+  , traverseBoth1
+  , foldMapWithKeyBoth1
+  , traverseWithKeyBoth1
+  ) where
+
+import Control.Applicative
+import Control.Arrow
+import Data.Key
+import Data.Functor.Apply
+import Data.Function (on)
+import Data.Monoid
+import Data.Stream.NonEmpty as NonEmpty hiding (toList)
+import Data.Foldable
+
+-- placeholder instances
+instance Foldable1 NonEmpty
+instance Traversable1 NonEmpty
+
+refill :: Traversable t => t a -> [b] -> t b
+refill t l = snd (mapAccumL (\(x:xs) _ -> (xs, x)) l t)
+
+toNonEmptyList :: Foldable1 f => f a -> NonEmpty a
+toNonEmptyList = NonEmpty.fromList . toList
+
+toKeyedNonEmptyList :: FoldableWithKey1 f => f a -> NonEmpty (Key f, a)
+toKeyedNonEmptyList = NonEmpty.fromList . toKeyedList
+
+foldMapBoth :: (Foldable f, Foldable g, Monoid m) => (a -> m) -> f a -> g a -> m
+foldMapBoth f as bs = go (toList as) (toList bs) where
+  go [] [] = mempty
+  go xs [] = foldMap f xs
+  go [] ys = foldMap f ys
+  go (x:xs) (y:ys) = f x `mappend` f y `mappend` go xs ys
+
+-- | traverse both containers, interleaving effects for fairness
+traverseBoth :: (Traversable f, Traversable g, Applicative m) => (a -> m b) -> f a -> g a -> m (f b, g b)
+traverseBoth f as bs = (refill as *** refill bs) <$> go (toList as) (toList bs)
+  where
+  go [] []         = pure ([],[])
+  go xs []         = flip (,) [] <$> traverse f xs
+  go [] ys         = (,) [] <$> traverse f ys
+  go (x:xs) (y:ys) = (\x y (xs,ys) -> (x:xs,y:ys)) <$> f x <*> f y <*> go xs ys
+
+-- | fold both containers, interleaving results for fairness
+foldMapBoth1 :: (Foldable1 f, Foldable1 g, Semigroup m) => (a -> m) -> f a -> g a -> m
+foldMapBoth1 f as bs = go (toNonEmptyList as) (toNonEmptyList bs)
+  where
+  go (x:|[])   (y:|[])   = f x <> f y
+  go (x:|z:zs) (y:|[])   = f x <> f y <> foldMap1 f (z:|zs)
+  go (x:|[])   ys        = f x <> foldMap1 f ys
+  go (x:|z:zs) (y:|w:ws) = f x <> f y <> go (z:|zs) (w:|ws)
+
+-- | traverse both containers, interleaving effects for fairness
+traverseBoth1 :: (Traversable1 f, Traversable1 g, Apply m) => (a -> m b) -> f a -> g a -> m (f b, g b)
+traverseBoth1 f as bs = (refill as *** refill bs) <$> go (toNonEmptyList as) (toNonEmptyList bs)
+  where
+  go (x:|[])   (y:|[])   = (\x' y'            -> ([x'],       [y']  )) <$> f x <.> f y
+  go (x:|z:zs) (y:|[])   = (\x' y' (x'':|xs') -> (x':x'':xs', [y']  )) <$> f x <.> f y <.> traverse1 f (z:|zs)
+  go (x:|[])   ys        = (\x' (y':|ys')     -> ([x'],       y':ys')) <$> f x <.> traverse1 f ys
+  go (x:|z:zs) (y:|w:ws) = (\x' y' (xs', ys') -> (x':xs',     y':ys')) <$> f x <.> f y <.> go (z:|zs) (w:|ws)
+
+foldMapWithKeyBoth 
+  :: (FoldableWithKey f, FoldableWithKey g, Monoid m) 
+  => (Key f -> a -> m) 
+  -> (Key g -> a -> m)
+  -> f a 
+  -> g a 
+  -> m
+foldMapWithKeyBoth f g as bs = go (toKeyedList as) (toKeyedList bs) where
+  f' = uncurry f
+  g' = uncurry g
+  go [] [] = mempty
+  go xs [] = foldMap f' xs
+  go [] ys = foldMap g' ys
+  go (x:xs) (y:ys) = f' x `mappend` g' y `mappend` go xs ys
+
+-- | traverse both containers, interleaving effects for fairness
+traverseWithKeyBoth 
+  :: (TraversableWithKey f, TraversableWithKey g, Applicative m) 
+  => (Key f -> a -> m b) 
+  -> (Key g -> a -> m b) 
+  -> f a 
+  -> g a 
+  -> m (f b, g b)
+traverseWithKeyBoth f g as bs = (refill as *** refill bs) <$> go (toKeyedList as) (toKeyedList bs)
+  where
+  f' = uncurry f
+  g' = uncurry g
+  go [] []         = pure ([],[])
+  go xs []         = flip (,) [] <$> traverse f' xs
+  go [] ys         = (,) [] <$> traverse g' ys
+  go (x:xs) (y:ys) = (\x y (xs,ys) -> (x:xs,y:ys)) <$> f' x <*> g' y <*> go xs ys
+
+-- | fold both containers, interleaving results for fairness
+foldMapWithKeyBoth1 
+  :: (FoldableWithKey1 f, FoldableWithKey1 g, Semigroup m) 
+  => (Key f -> a -> m) 
+  -> (Key g -> a -> m) 
+  -> f a 
+  -> g a 
+  -> m
+foldMapWithKeyBoth1 f g as bs = go (toKeyedNonEmptyList as) (toKeyedNonEmptyList bs)
+  where
+  f' = uncurry f
+  g' = uncurry g
+  go (x:|[])   (y:|[])   = f' x <> g' y
+  go (x:|z:zs) (y:|[])   = f' x <> g' y <> foldMap1 f' (z:|zs)
+  go (x:|[])   ys        = f' x <> foldMap1 g' ys
+  go (x:|z:zs) (y:|w:ws) = f' x <> g' y <> go (z:|zs) (w:|ws)
+
+-- | traverse both containers, interleaving effects for fairness
+traverseWithKeyBoth1 
+  :: (TraversableWithKey1 f, TraversableWithKey1 g, Apply m) 
+  => (Key f -> a -> m b) 
+  -> (Key g -> a -> m b) 
+  -> f a 
+  -> g a 
+  -> m (f b, g b)
+traverseWithKeyBoth1 f g as bs = (refill as *** refill bs) <$> go (toKeyedNonEmptyList as) (toKeyedNonEmptyList bs)
+  where
+  f' = uncurry f
+  g' = uncurry g
+  go (x:|[])   (y:|[])   = (\x' y'            -> ([x'],      [y']  )) <$> f' x <.> g' y
+  go (x:|z:zs) (y:|[])   = (\x' y' (z':|zs')  -> (x':z':zs', [y']  )) <$> f' x <.> g' y <.> traverse1 f' (z:|zs)
+  go (x:|[])   ys        = (\x' (y':|ys')     -> ([x'],      y':ys')) <$> f' x <.> traverse1 g' ys
+  go (x:|z:zs) (y:|w:ws) = (\x' y' (xs', ys') -> (x':xs',    y':ys')) <$> f' x <.> g' y <.> go (z:|zs) (w:|ws)
diff --git a/representable-tries.cabal b/representable-tries.cabal
--- a/representable-tries.cabal
+++ b/representable-tries.cabal
@@ -1,6 +1,6 @@
 name:          representable-tries
 category:      Data Structures, Functors, Monads, Comonads
-version:       0.2.3.1
+version:       0.3
 license:       BSD3
 cabal-version: >= 1.6
 license-file:  LICENSE
@@ -37,7 +37,6 @@
     Data.Functor.Representable.Trie
     Data.Functor.Representable.Trie.Bool
     Data.Functor.Representable.Trie.List
-    Data.Semigroupoid.Trie
+    Data.Traversable.Fair
 
   ghc-options: -Wall
-
