In the following code I got warning Orphan instance: instance (MonadIO m, Monad m) => GenerateUUID m
instance (MonadIO m, Monad m) => GenerateUUID m where
generateUUID = liftIO nextRandom
According to it the solution is either
move the instance declaration to the module of the class or of the type, or
wrap the type with a newtype and declare the instance on the new type.
(or disable the warning hat Internet also suggest)
My problem is that I'm not able to find how to wrap the type with a newtype?
You can define a newtype wrapper like this:
newtype Foo m a = Foo { unFoo :: m a }
If we also want to say "I want Foo
to have the same instances for Functor
, Monad
, Applicative
... that m
has, the only difference being that the methods use Foo m a
instead of m a
" we can use the -XDerivingVia
extension:
{-# LANGUAGE DerivingVia #-}
newtype Foo m a = Foo { unFoo :: m a }
deriving (Functor,Applicative,Monad,MonadIO,GenerateUUID) via m
Any time the compiler complains about a missing instance for Foo
, add it to the deriving
clause.
A slight refinement. Suppose we also wanted to "inherit" Semigroup
and Monoid
instances. For example: IO ()
is a Monoid
, so we might want Foo IO ()
to be a Monoid
as well. We need a separate deriving
clause:
newtype Foo m a = Foo { unFoo :: m a }
deriving (Functor,Applicative,Monad,MonadIO) via m
deriving (Semigroup,Monoid) via (m a)
Why a separate clause? Because the typeclasses have different kinds. Functor
has kind (Type -> Type) -> Constraint
and we are declaring the instance for Foo m
, which has kind Type -> Type
.
Meanwhile, Semigroup
has kind Type -> Constraint
and we are declaring the instance for Foo m a
, the "fully applied" type constructor with kind Type
.