relude-1.2.0.0: src/Relude/Extra/Bifunctor.hs
{-# LANGUAGE Safe #-}
{- |
Module : Relude.Extra.Bifunctor
Copyright : (c) 2018-2023 Kowainik
SPDX-License-Identifier : MIT
Maintainer : Kowainik <xrom.xkov@gmail.com>
Stability : Stable
Portability : Portable
Useful combinators for bifunctors inside functors. This set of functions is
useful when you want to work with types like these ones:
@
foo :: IO (Either a b)
bar :: IO (a, b)
baz :: Maybe (Either a b)
qux :: Maybe (a, b)
doo :: (a, a)
dee :: Either a a
@
@since 0.1.0
-}
module Relude.Extra.Bifunctor
( bimapBoth
, bimapF
, firstF
, secondF
) where
import Relude
{- | Maps a function over both elements of a bifunctor.
>>> bimapBoth length ([True], [False, True])
(1,2)
>>> map (bimapBoth not) [Left True, Right False]
[Left False,Right True]
@since 0.6.0.0
-}
bimapBoth :: Bifunctor f => (a -> b) -> f a a -> f b b
bimapBoth f = bimap f f
{-# INLINE bimapBoth #-}
{- | Fmaps functions for nested bifunctor. Short for @fmap (bimap f g)@.
>>> bimapF not length $ Just (False, ['a', 'b'])
Just (True,2)
@since 0.1.0
-}
bimapF :: (Functor f, Bifunctor p) => (a -> c) -> (b -> d) -> f (p a b) -> f (p c d)
bimapF f g = fmap (bimap f g)
{-# INLINE bimapF #-}
{- | Short for @fmap . first@.
>>> firstF not $ Just (False, ['a', 'b'])
Just (True,"ab")
@since 0.1.0
-}
firstF :: (Functor f, Bifunctor p) => (a -> c) -> f (p a b) -> f (p c b)
firstF = fmap . first
{-# INLINE firstF #-}
{- | Short for @fmap . second@.
>>> secondF length $ Just (False, ['a', 'b'])
Just (False,2)
@since 0.1.0
-}
secondF :: (Functor f, Bifunctor p) => (b -> d) -> f (p a b) -> f (p a d)
secondF = fmap . second
{-# INLINE secondF #-}