我试图在一个简单的生产系统中采用ReaderT模式的想法。
在原始示例中,数据类型Env定义为:
data Env = Env
{ envLog :: !(String -> IO ())
, ...
}
Run Code Online (Sandbox Code Playgroud)
在我的实现中,我定义了一个类型类Serializable来帮助我记录不同的数据类型。这样我就可以拥有更通用的日志记录功能(包括不同文件格式的序列化):
data Env = Env
{ evnLog :: (Serializable a) => a -> FilePath -> IO ()
, ...
}
Run Code Online (Sandbox Code Playgroud)
当然,这是行不通的。错误消息是:
Not in scope: type variable ‘a’
|
61 | { envLog :: (Serializable a) =>
| ^
Run Code Online (Sandbox Code Playgroud)
如果a包含在的Type构造函数中Env,我将被迫不断地在ReaderT中更改Context信息,这确实很麻烦。
我只想将此通用函数传递给一系列计算,并在需要时使用它。
是否有可能不引入 aType的Type构造函数Env?也许ReaderT模式需要更多技巧来使用?
您正在尝试使用等级2类型(特别是Env数据构造函数的类型)。您既需要启用RankNTypes扩展名,也要使用a,forall因为永远不会推断等级2类型:
{-# LANGUAGE RankNTypes #-}
data Env = Env
{ envLog :: forall a. (Serializable a) => a -> FilePath -> IO ()
, ...
}
Run Code Online (Sandbox Code Playgroud)