----------------

-- | Fold a value using a specified 'Fold' and 'Monoid' operations.
-- This is like 'foldBy' where the 'Foldable' instance can be
-- manually specified.
--
-- @
-- 'foldByOf' 'folded' ≡ 'foldBy'
-- @
--
-- @
-- 'foldByOf' :: 'Getter' s a     -> (a -> a -> a) -> a -> s -> a
-- 'foldByOf' :: 'Fold' s a       -> (a -> a -> a) -> a -> s -> a
-- 'foldByOf' :: 'Lens'' s a      -> (a -> a -> a) -> a -> s -> a
-- 'foldByOf' :: 'Traversal'' s a -> (a -> a -> a) -> a -> s -> a
-- 'foldByOf' :: 'Iso'' s a       -> (a -> a -> a) -> a -> s -> a
-- @
--
-- >>> foldByOf both (++) [] ("hello","world")
-- "helloworld"
foldByOf :: Fold s a -> (a -> a -> a) -> a -> s -> a
foldByOf l f z = reifyMonoid f z (foldMapOf l ReflectedMonoid)

-- | Fold a value using a specified 'Fold' and 'Monoid' operations.
-- This is like 'foldMapBy' where the 'Foldable' instance can be
-- manually specified.
--
-- @
-- 'fo
foldByOf :: Fold s a -> (a -> a -> a) -> a -> s -> a
foldByOf l f z = reifyMonoid f z (foldMapOf l ReflectedMonoid)
foldByOf l f z = reifyMonoid f z (foldMapOf l ReflectedMonoid)