Say we have a data type defined as
data A a = A' a deriving Show 
We have
A :: * -> *
We can then make A an instance of Functor:
instance Functor A where fmap f (A' x) = A' (f x)
This allows us to make a value of type A and use fmap to apply a function to the wrapped value
Prelude> let x = A' 1
Prelude> fmap (+1) x
A' 2
Now, if we defined A as
data A = A' Int deriving Show
The kind of A is
A :: *
Consequently, we can not make A an instance of Functor -
instance Functor A where fmap f (A' x) = A' (f x)
<interactive>:4:18:
    Kind mis-match
    The first argument of `Functor' should have kind `* -> *',
    but `A' has kind `*'
    In the instance declaration for `Functor A'
My question is, is there a generic way to apply a function to the wrap value for data types of kind * with a data constructor that only takes one parameter (i.e., something analogous to fmap)? It's fairly easy to write custom function:
Prelude> let myFmap f (A' x) = A' (f x)
Prelude> let x = A' 1
Prelude> myFmap (+1) x
A' 2
It's also possible to make A an instance of Num:
instance Num A where (+) (A' x) (A' y) = A' (x + y) -- Ignoring the warnings
Prelude> A' 1 + A' 1 
A' 2
Both of these approaches work but is there a better way that I am missing?
I don't think there's a good generic solution for the second half of the question, but I can at least answer the first half.
This is the purpose of the mono-traversable package, which provides a MonoFunctor typeclass. The instance for A' would be:
type instance Element A' = Int
instance MonoFunctor a' where
  omap f (A' i) = A' (f i)
YMMV on how useful this is versus a simple a'map :: (Int -> Int) -> A' -> A' function or a lens.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With