为预先存在的类型自动生成“PersistEntity”
Automatically generating `PersistEntity` for pre-existing types
动机:想用MongoDB来存储数据。持久库似乎是唯一支持 MongoDB 的高级 Haskell 库。我的项目已经定义了表示任何数据库的行(文档)的类型。
persistent 的典型用途是通过一些模板 Haskell 来定义您的类型,例如:
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
import Database.Persist
import Database.Persist.TH
import Database.Persist.Sqlite
import Control.Monad.IO.Class (liftIO)
mkPersist mongoSettings [persistLowerCase|
Person
name String
age Int
deriving Show
|]
但是,我已经在类似于以下的代码中拥有相当大的类型:
newtype Name = Name String deriving (Show, Etc, Etc)
data Person = Person
{ name :: Name, age :: Int } deriving (Show, Etc, Etc)
所以理想情况下,我会通过精简的 TH 获得我的 PersistEntity
甚至 PersistField
实例,例如:
mkPersistFromType mongoSettings ''Person
但是,没有mkPersistFromType
那样的TH功能。手写 class 个实例很乏味——它们非常长。什么是正确的前进方向?有没有我没见过的 mkPersistFromType
或者我应该自己写?
注意 mkPersist
只是一个函数,它 returns 是要添加到源文件的声明列表。所以你可以自由地 post 处理这个声明,例如删除不需要的。
这是我过滤掉所有数据声明的示例:
myMkPersist settings = do
filter wanted <$> mkPersist settings [persistLowerCase|
Person
name String
|]
where
wanted DataD{} = False
wanted _ = True
请注意,由于阶段限制,myMkPersist
应在单独的文件中定义。在主文件中使用这个函数:
data Person = Person
{ personName :: String
}
myMkPersist mongoSettings
此外,您可能还想检查 mkPersist
上的输出,以了解您希望如何 post 处理声明,您可以使用 -ddump-splices
cli 选项来实现。
动机:想用MongoDB来存储数据。持久库似乎是唯一支持 MongoDB 的高级 Haskell 库。我的项目已经定义了表示任何数据库的行(文档)的类型。
persistent 的典型用途是通过一些模板 Haskell 来定义您的类型,例如:
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
import Database.Persist
import Database.Persist.TH
import Database.Persist.Sqlite
import Control.Monad.IO.Class (liftIO)
mkPersist mongoSettings [persistLowerCase|
Person
name String
age Int
deriving Show
|]
但是,我已经在类似于以下的代码中拥有相当大的类型:
newtype Name = Name String deriving (Show, Etc, Etc)
data Person = Person
{ name :: Name, age :: Int } deriving (Show, Etc, Etc)
所以理想情况下,我会通过精简的 TH 获得我的 PersistEntity
甚至 PersistField
实例,例如:
mkPersistFromType mongoSettings ''Person
但是,没有mkPersistFromType
那样的TH功能。手写 class 个实例很乏味——它们非常长。什么是正确的前进方向?有没有我没见过的 mkPersistFromType
或者我应该自己写?
注意 mkPersist
只是一个函数,它 returns 是要添加到源文件的声明列表。所以你可以自由地 post 处理这个声明,例如删除不需要的。
这是我过滤掉所有数据声明的示例:
myMkPersist settings = do
filter wanted <$> mkPersist settings [persistLowerCase|
Person
name String
|]
where
wanted DataD{} = False
wanted _ = True
请注意,由于阶段限制,myMkPersist
应在单独的文件中定义。在主文件中使用这个函数:
data Person = Person
{ personName :: String
}
myMkPersist mongoSettings
此外,您可能还想检查 mkPersist
上的输出,以了解您希望如何 post 处理声明,您可以使用 -ddump-splices
cli 选项来实现。