A likely cause of the problem is that you are importing the ReaderT
type, but not the ReaderT
value constructor, that is, the function of type (r -> m a) -> ReaderT r m a
that builds values of type ReaderT
.
For example, you might have written
import Control.Monad.Reader ( ReaderT ) -- only the ReaderT type
instead of
import Control.Monad.Reader -- import everything
or
import Control.Monad.Reader ( ReaderT(..) ) -- import the type and its constuctor
But, why is it necessary for the ReaderT
value constructor to be in scope?
The reason is that DerivingVia
relies on Data.Coerce
under the hood. In the module which defines the instance, we must be able to coerce to the "via" type, in this case ReaderT (Set HiPermission) IO
.
And, as it turns out, to be able to wrap/unwrap a newtype like ReaderT
using coercions, we need to have its value constructor in scope. Quoting from the coerce Haddocks:
The third kind of instance exists for every newtype NT = MkNT T and
comes in two variants, namely
instance Coercible a T => Coercible a NT
instance Coercible T b => Coercible NT b
This instance is only usable if the constructor MkNT is in scope.