Bitraversable identifies bifunctorial data structures whose elements can be traversed in order, performing Applicative or Monad actions at each element, and collecting a result structure with the same shape.
As opposed to Traversable data structures, which have one variety of element on which an action can be performed, Bitraversable data structures have two such varieties of elements.
A definition of bitraverse must satisfy the following laws:
- Naturality
bitraverse (t . f) (t . g) ≡ t . bitraverse f gfor every applicative transformation
t- Identity
- Composition
Compose . fmap (bitraverse g1 g2) . bitraverse f1 f2 ≡ bitraverse (Compose . fmap g1 . f1) (Compose . fmap g2 . f2)
where an applicative transformation is a function
t :: (Applicative f, Applicative g) => f a -> g apreserving the Applicative operations:
t (pure x) ≡ pure x
t (f <*> x) ≡ t f <*> t x
and the identity functor Identity and composition functors Compose are from Data.Functor.Identity and Data.Functor.Compose.
Some simple examples are Either and (,):
instance Bitraversable Either where
bitraverse f _ (Left x) = Left <$> f x
bitraverse _ g (Right y) = Right <$> g y
instance Bitraversable (,) where
bitraverse f g (x, y) = (,) <$> f x <*> g yBitraversable relates to its superclasses in the following ways:
bimap f g ≡ runIdentity . bitraverse (Identity . f) (Identity . g)
bifoldMap f g ≡ getConst . bitraverse (Const . f) (Const . g)
These are available as bimapDefault and bifoldMapDefault respectively.
If the type is also an instance of Traversable, then it must satisfy (up to laziness):
traverse ≡ bitraverse pure
Methods
bitraverse :: Applicative f => (a -> f c) -> (b -> f d) -> t a b -> f (t c d)Evaluates the relevant functions at each element in the structure, running the action, and builds a new structure with the same shape, using the results produced from sequencing the actions.
bitraverse f g ≡ bisequenceA . bimap f gFor a version that ignores the results, see bitraverse_.
Examples
Basic usage:
Example1 expression bitraverse listToMaybe (find odd) (Left [])Nothing
Example1 expression bitraverse listToMaybe (find odd) (Left [1, 2, 3])Just (Left 1)
Example1 expression bitraverse listToMaybe (find odd) (Right [4, 5])Just (Right 5)
Example1 expression bitraverse listToMaybe (find odd) ([1, 2, 3], [4, 5])Just (1,5)
Example1 expression bitraverse listToMaybe (find odd) ([], [4, 5])Nothing
Instances11Bitraversable, …
Bitraversable ArgDefined in base-4.20.2.0 · Data.SemigroupBitraversable EitherDefined in base-4.20.2.0 · Data.BitraversableBitraversable Tuple2Defined in base-4.20.2.0 · Data.BitraversableClass laws for tuples hold only up to laziness. The Bitraversable methods are lazier than their Traversable counterparts. For example the law
bitraverse pure ≡ traversedoes not hold for tuples if laziness is exploited:Example2 expressions (bitraverse pure pure undefined :: IO (Int, Word)) `seq` ()()(traverse pure undefined :: IO (Int, Word)) `seq` ()*** Exception: Prelude.undefined
Bitraversable ConstDefined in base-4.20.2.0 · Data.BitraversableBitraversable ConstantDefined in transformers-0.6.1.1 · Data.Functor.ConstantBitraversable (Tuple3 x)Defined in base-4.20.2.0 · Data.BitraversableBitraversable (K1 i)Defined in base-4.20.2.0 · Data.BitraversableBitraversable (Tuple4 x y)Defined in base-4.20.2.0 · Data.BitraversableBitraversable (Tuple5 x y z)Defined in base-4.20.2.0 · Data.BitraversableBitraversable (Tuple6 x y z w)Defined in base-4.20.2.0 · Data.BitraversableBitraversable (Tuple7 x y z w v)Defined in base-4.20.2.0 · Data.Bitraversable