    {-# LANGUAGE DefaultSignatures #-}
    {-# LANGUAGE TypeOperators #-}
    module Foundation.Collection.InnerFunctor
        ( InnerFunctor(..)
        ) where

    import Basement.Compat.Base
    import Foundation.Collection.Element
    import qualified Basement.String as S
    import qualified Basement.UArray as UV
    import           Basement.BoxedArray (Array)

    -- | A monomorphic functor that maps the inner values to values of the same type
    class InnerFunctor c where
        imap :: (Element c -> Element c) -> c -> c
        default imap :: (Functor f, Element (f a) ~ a, f a ~ c) => (Element c -> Element c) -> c -> c
        imap = (a -> a) -> f a -> f a
    (Element c -> Element c) -> c -> c
    forall a b. (a -> b) -> f a -> f b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap

    instance InnerFunctor [a]

    instance UV.PrimType ty => InnerFunctor (UV.UArray ty) where
        imap :: (Element (UArray ty) -> Element (UArray ty))
    -> UArray ty -> UArray ty
    imap = (ty -> ty) -> UArray ty -> UArray ty
    (Element (UArray ty) -> Element (UArray ty))
    -> UArray ty -> UArray ty
    forall a b.
    (PrimType a, PrimType b) =>
    (a -> b) -> UArray a -> UArray b
    UV.map

    instance InnerFunctor (Array ty)

    instance InnerFunctor S.String where
        imap :: (Element String -> Element String) -> String -> String
    imap = (Char -> Char) -> String -> String
    (Element String -> Element String) -> String -> String
    S.charMap