{-# LANGUAGE TupleSections #-} {- | Copyright: (c) 2018-2019 Kowainik License: MIT Maintainer: Kowainik <xrom.xkov@gmail.com> Contains utility functions for working with tuples. -} module Relude.Extra.Tuple ( dupe , mapToFst , mapToSnd , mapBoth , traverseToFst , traverseToSnd , traverseBoth ) where import Relude {- | Creates a tuple by pairing something with itself. >>> dupe "foo" ("foo","foo") >>> dupe () ((),()) -} dupe :: a -> (a, a) dupe a = (a, a) {-# INLINE dupe #-} {- | Apply a function, with the result in the fst slot, and the value in the other. A dual to 'mapToSnd' >>> mapToFst (+1) 10 (11,10) -} mapToFst :: (a -> b) -> a -> (b, a) mapToFst f a = (f a, a) {-# INLINE mapToFst #-} {- | Apply a function, with the result in the second slot, and the value in the other. A dual to 'mapToFst'. >>> mapToSnd (+1) 10 (10,11) -} mapToSnd :: (a -> b) -> a -> (a, b) mapToSnd f a = (a, f a) {-# INLINE mapToSnd #-} {- | Maps a function over both elements of a tuple. >>> mapBoth ("Hello " <>) ("Alice", "Bob") ("Hello Alice","Hello Bob") -} mapBoth :: (a -> b) -> (a, a) -> (b, b) mapBoth f (a1, a2) = (f a1, f a2) {-# INLINE mapBoth #-} {- | Apply a function that returns a value inside of a functor, with the output in the first slot, the input in the second, and the entire tuple inside the functor. A dual to 'traverseToSnd' >>> traverseToFst (Just . (+1)) 10 Just (11,10) >>> traverseToFst (const Nothing) 10 Nothing -} traverseToFst :: Functor t => (a -> t b) -> a -> t (b, a) traverseToFst f a = (,a) <$> f a {-# INLINE traverseToFst #-} {- | Apply a function that returns a value inside of a functor, with the output in the second slot, the input in the first, and the entire tuple inside the functor. A dual to 'traverseToFst'. >>> traverseToSnd (Just . (+1)) 10 Just (10,11) >>> traverseToSnd (const Nothing) 10 Nothing -} traverseToSnd :: Functor t => (a -> t b) -> a -> t (a, b) traverseToSnd f a = (a,) <$> f a {-# INLINE traverseToSnd #-} {- | Maps a function that returns a value inside of an applicative functor over both elements of a tuple, with the entire tuple inside the applicative functor. >>> traverseBoth (Just . ("Hello " <>)) ("Alice", "Bob") Just ("Hello Alice","Hello Bob") >>> traverseBoth (const Nothing) ("Alice", "Bob") Nothing -} traverseBoth :: Applicative t => (a -> t b) -> (a, a) -> t (b, b) traverseBoth f (a1, a2) = (,) <$> f a1 <*> f a2 {-# INLINE traverseBoth #-}