module FoldlHelp
    ( minimumOn
    , premapMaybe
    , module Control.Foldl
    ) where
import Control.Foldl

data Maybe' a = Just' !a | Nothing'
data Pair a b = !a :!: !b

minimumOn :: Ord b => (a -> b) -> Fold a (Maybe a)
minimumOn f = Fold step Nothing' extract
  where
    extract Nothing' = Nothing
    extract (Just' (a :!: _)) = Just a
    step Nothing' b = Just' (b :!: f b)
    step (Just' (a :!: x)) b
        | y < x     = Just' (b :!: y)
        | otherwise = Just' (a :!: x)
      where
        y = f b

premapMaybe :: (a -> Maybe b) -> Fold b r -> Fold a r
{-# INLINABLE premapMaybe #-}
premapMaybe f (Fold step initial extract) = Fold step' initial extract
  where
    step' x a = case f a of
        Nothing -> x
        Just s  -> step x s
