[英]Is it possible to define your own Persistent / Esqueleto lens?
給定以下持久性類型:
share
[mkPersist sqlSettings, mkMigrate "migrateAll"]
[persistLowerCase|
Account
email Text
passphrase Text
firstName Text
lastName Text
deriving Eq Show Generic
|]
我認為是生成一種透鏡,即AccountEmail
, AccountPassphrase
等。是否可以通過這種方式將它們組合在一起,而不一定是組合,而是說字符串連接,所以我經常發現自己正在編寫以下類型的函數:
accountFullName :: SqlExpr (Entity Account) -> SqlExpr Text
accountFullName acc = acc ^. AccountFirstName ++. val " " ++. acc ^. AccountLastName
如果可以用類似於Account*
方式定義它,那么可以使用^.
進行調用^.
而不是使用原始函數,即acc ^. AccountFullName
acc ^. AccountFullName
。 這可能不是使用這些訪問器的適當方法,但是如果不是這樣,我很想知道為什么我認為這可能有助於進一步理解Persistent庫的這一部分,因為當我看時我感到相當迷失在EntityField
周圍的代碼中...
這是不可能的。
(^.) :: (PersistEntity val, PersistField typ)
=> expr (Entity val)
-> EntityField val typ
-> expr (Value typ)
您將看到第二個參數是EntityField val typ
,它是PersistEntity val
類中定義的類型族。 這是為您的表預先定義的,無法更改,因此該特定運算符無法按您希望的方式用於自定義訪問器。
當您使用persistLowerCase
和朋友時,它將使用Template Haskell解析您的定義並生成適當的數據定義。 據我了解,會生成類似於以下內容的內容:
data Account = Account
{ accountEmail :: Text
, accountPassphrase :: Text
, accountFirstName :: Text
, accountLastName :: Text
}
data AccountField a where
AccountId :: AccountField Key
AccountEmail :: AccountField Text
AccountPassphrase :: AccountField Text
AccountFirstName :: AccountField Text
AccountLastName :: AccountField Text
instance PersistEntity Account where
data EntityField Account a = AccountField a
...
(這在語法上並不准確,並且缺少很多細節,但是我認為可以為這種情況提供足夠的上下文。)
因此,您傳遞給(^.)
的“鏡頭”實際上只是與表類型Account
關聯的類型的構造函數。 您無法創建新的構造函數或動態重新關聯類型家族,因此您無法進行其他可傳遞給(^.)
。 這些訪問器有效地固定在石頭上。
我認為僅使用原始函數是最有意義的。 accountFullName acc
編寫起來還不錯,而且很顯然,您所做的事情比僅提取字段值還要復雜一些。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.