{-# 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