    -- |
    -- Module      : Data.Vector.Fusion.Util
    -- Copyright   : (c) Roman Leshchinskiy 2009
    --                   Alexey Kuleshevich 2020-2022
    --                   Aleksey Khudyakov 2020-2022
    --                   Andrew Lelechenko 2020-2022
    -- License     : BSD-style
    --
    -- Maintainer  : Haskell Libraries Team <libraries@haskell.org>
    -- Stability   : experimental
    -- Portability : portable
    --
    -- Fusion-related utility types
    --

    module Data.Vector.Fusion.Util (
      Id(..), Box(..), liftBox,

      delay_inline, delayed_min
    ) where

    import Data.Stream.Monadic (Box(..), liftBox)

    -- | Identity monad
    newtype Id a = Id { forall a. Id a -> a
    unId :: a }

    instance Functor Id where
      fmap :: forall a b. (a -> b) -> Id a -> Id b
    fmap a -> b
    f (Id a
    x) = b -> Id b
    forall a. a -> Id a
    Id (a -> b
    f a
    x)

    instance Applicative Id where
      pure :: forall a. a -> Id a
    pure = a -> Id a
    forall a. a -> Id a
    Id
      Id a -> b
    f <*> :: forall a b. Id (a -> b) -> Id a -> Id b
    <*> Id a
    x = b -> Id b
    forall a. a -> Id a
    Id (a -> b
    f a
    x)

    instance Monad Id where
      return :: forall a. a -> Id a
    return = a -> Id a
    forall a. a -> Id a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure
      Id a
    x >>= :: forall a b. Id a -> (a -> Id b) -> Id b
    >>= a -> Id b
    f = a -> Id b
    f a
    x

    -- | Delay inlining a function until late in the game (simplifier phase 0).
    delay_inline :: (a -> b) -> a -> b
    {-# INLINE [0] delay_inline #-}
    delay_inline :: forall a b. (a -> b) -> a -> b
    delay_inline a -> b
    f = a -> b
    f

    -- | `min` inlined in phase 0
    delayed_min :: Int -> Int -> Int
    {-# INLINE [0] delayed_min #-}
    delayed_min :: Int -> Int -> Int
    delayed_min Int
    m Int
    n = Int -> Int -> Int
    forall a. Ord a => a -> a -> a
    min Int
    m Int
    n