2016-12-13 53 views
1

雖然玩弄persistent,我不知道PersistStoreWrite (BaseBackend b)約束來自哪裏。我在insert的簽名上看不到它。PersistStoreWrite(BaseBackend x)約束來自何時使用通用持久?

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) 

以上工作正常,但如果我刪除所提到的約束,編譯器會抱怨(「從使用的insert引起」)。 我用lts-7.12解析器(GHC 8,持久性2.6)使用堆棧。備案

數據定義:

share [mkPersist sqlSettings{mpsGeneric = True}, mkMigrate "migrateAll"] [persistLowerCase| 
TaskItem 
    name Text 
    submittedAt UTCTime 
    deriving Show 

回答

0

奇怪的是,也get方法所需的BaseBackend寫。正如@snoyman暗示的,這部分是由於生成的TH代碼。在TH-產生拼接的部分:

instance PersistStore backend => 
     PersistEntity (TaskItemGeneric backend) where 
    type PersistEntityBackend (TaskItemGeneric backend) = backend 

注意PersistStore是一個別名PersistStoreWrite。這與上PersistStoreReadget方法約束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)