Before getting carried away, you should keep in mind that you're trying to avoid (1) naming and (2) writing the monomorphic function:
mapFoo :: (Int -> Int) -> (Foo -> Foo)
mapFoo f (Foo ints) = Foo (f <$> ints)
If you really don't want to give this function a separate name and want GHC to write the function for you, I think the only sensible way is to re-define your type as a proper functor of kind * -> *
with an automatically derived instance:
newtype FooF a = Foo [a] deriving (Functor)
and then define a type alias for the specialization to Int
:
type Foo = FooF Int
This is not precisely equivalent to your original definition of Foo
. In particular, the following expression in isolation:
Foo [1,2,3]
will have type Num a => FooF a
instead of type Foo = FooF Int
, so GHC may fail to infer types in all the places it used to. But, this Foo
type alias will mostly behave like your original Foo
newtype and will allow you to write:
fmap (*5) $ Foo [1,2,3]
and such.
On the other hand, if you want to keep your newtype the same, don't mind writing the function yourself, yet don't want to give that function a separate name, you can't use fmap
(at least not without overriding the prelude definition, which kind of defeats the purpose). However, as per @leftroundabout's answer, you can use omap
from the mono-traversable
package. Because this requires you to define the function yourself in a MonoFunctor Foo
instance (e.g., using the same definition as mapFoo
above), there's no real point unless you're doing this for a bunch of non-functors besides Foo
and want to use a single omap
name for all of them or want to write functions that can handle any such MonoFunctor
uniformly.
Functor
, as functors must have at least one type variable. For instance,newtype Foo' a = Foo' ([a])
would be a functor. However, even though this is not a functor, it is still entirely possible to write a mapping functionfoomap :: (Int -> Int) -> Foo -> Foo
. – bradrn