3

我正在使用 ReaderT 为这种类型编写 Monad 实例并通过

newtype HIO a = HIO {runHIO :: Set HiPermission -> IO a}

我试过这样做

newtype HIO a = HIO {runHIO :: Set HiPermission -> IO a}
  deriving (Functor, Applicative, Monad) via (ReaderT (Set HiPermission) IO) 

但出现错误:

Couldn't match representation of type `Set HiPermission -> IO c' with that of `ReaderT (Set HiPermission) IO c' 
arising from the coercion of the method

我究竟做错了什么?

4

1 回答 1

2

问题的一个可能原因是您正在导入ReaderT类型,而不是ReaderT 值构造函数,(r -> m a) -> ReaderT r m a即构建类型值的类型函数ReaderT

例如,你可能写过

import Control.Monad.Reader ( ReaderT ) -- only the ReaderT type

代替

import Control.Monad.Reader -- import everything

或者

import Control.Monad.Reader ( ReaderT(..) ) -- import the type and its constuctor

但是,为什么ReaderT值构造函数必须在范围内?

原因是DerivingVia依赖于Data.Coerce引擎盖下。在定义实例的模块中,我们必须能够强制转换为“via”类型,在这种情况下ReaderT (Set HiPermission) IO

而且,事实证明,为了能够像ReaderT使用强制转换一样包装/解包新类型,我们需要将其值构造函数放在作用域内。引用强制黑线鳕

第三种实例存在于每个新类型 NT = MkNT T 中,并且有两种变体,即

instance Coercible a T => Coercible a NT

instance Coercible T b => Coercible NT b

这个实例只有在构造函数 MkNT 在范围内时才可用。

于 2022-01-13T13:58:39.803 回答