使用通用 Persistent 时,PersistStoreWrite (BaseBackend x) 约束从何而来?
Where does PersistStoreWrite (BaseBackend x) constraint come from when using generic Persistent?
在玩弄 persistent
时,我无法弄清楚 PersistStoreWrite (BaseBackend b)
约束从何而来。我在insert
.
的签名上看不到
x :: (
MonadIO m,
PersistStoreRead b,
PersistStoreWrite b,
PersistStoreWrite (BaseBackend b) -- <--- where does this come from?
) => ReaderT b m ()
x = do
now <- liftIO getCurrentTime
aTaskId <- insert (TaskItem "Hello" now)
aTask <- get aTaskId
liftIO (print aTask)
以上工作正常,但如果我删除提到的约束,编译器会抱怨 ("arising from a use of insert
")。
我将堆栈与 lts-7.12 解析器(GHC 8,持久性 2.6)一起使用。
记录的数据定义:
share [mkPersist sqlSettings{mpsGeneric = True}, mkMigrate "migrateAll"] [persistLowerCase|
TaskItem
name Text
submittedAt UTCTime
deriving Show
奇怪的是,get
方法也需要 BaseBackend
写入。正如@snoyman 所暗示的,这部分是由于生成的 TH 代码。部分TH生成的拼接:
instance PersistStore backend =>
PersistEntity (TaskItemGeneric backend) where
type PersistEntityBackend (TaskItemGeneric backend) = backend
请注意 PersistStore
是 PersistStoreWrite
的别名。这与 PersistStoreRead
的 get
方法上的约束 PersistRecordBackend record backend
相结合,扩展为:
type PersistRecordBackend record backend =
(PersistEntity record, PersistEntityBackend record ~ BaseBackend backend)
确实导致推断约束 PersistStoreWrite (BaseBackend backend)
。
解决方案
事实上这是微不足道的 - 明智的 BaseBackend
应该始终支持写入。所以我只是为约束添加了别名:
type PersistRead b = (PersistStoreRead b, PersistStoreWrite (BaseBackend b))
type PersistWrite b = (PersistRead b, PersistStoreWrite b)
所以
x :: (MonadIO m, PersistWrite b) => ReaderT b m ()
x = do
now <- liftIO getCurrentTime
aTaskId <- insert (TaskItem "Hello" now)
aTask <- get aTaskId
liftIO (print aTask)
在玩弄 persistent
时,我无法弄清楚 PersistStoreWrite (BaseBackend b)
约束从何而来。我在insert
.
x :: (
MonadIO m,
PersistStoreRead b,
PersistStoreWrite b,
PersistStoreWrite (BaseBackend b) -- <--- where does this come from?
) => ReaderT b m ()
x = do
now <- liftIO getCurrentTime
aTaskId <- insert (TaskItem "Hello" now)
aTask <- get aTaskId
liftIO (print aTask)
以上工作正常,但如果我删除提到的约束,编译器会抱怨 ("arising from a use of insert
")。
我将堆栈与 lts-7.12 解析器(GHC 8,持久性 2.6)一起使用。
记录的数据定义:
share [mkPersist sqlSettings{mpsGeneric = True}, mkMigrate "migrateAll"] [persistLowerCase|
TaskItem
name Text
submittedAt UTCTime
deriving Show
奇怪的是,get
方法也需要 BaseBackend
写入。正如@snoyman 所暗示的,这部分是由于生成的 TH 代码。部分TH生成的拼接:
instance PersistStore backend =>
PersistEntity (TaskItemGeneric backend) where
type PersistEntityBackend (TaskItemGeneric backend) = backend
请注意 PersistStore
是 PersistStoreWrite
的别名。这与 PersistStoreRead
的 get
方法上的约束 PersistRecordBackend record backend
相结合,扩展为:
type PersistRecordBackend record backend =
(PersistEntity record, PersistEntityBackend record ~ BaseBackend backend)
确实导致推断约束 PersistStoreWrite (BaseBackend backend)
。
解决方案
事实上这是微不足道的 - 明智的 BaseBackend
应该始终支持写入。所以我只是为约束添加了别名:
type PersistRead b = (PersistStoreRead b, PersistStoreWrite (BaseBackend b))
type PersistWrite b = (PersistRead b, PersistStoreWrite b)
所以
x :: (MonadIO m, PersistWrite b) => ReaderT b m ()
x = do
now <- liftIO getCurrentTime
aTaskId <- insert (TaskItem "Hello" now)
aTask <- get aTaskId
liftIO (print aTask)