簡體   English   中英

是否可以定義自己的Persistent / Esqueleto鏡片?

[英]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
|]

我認為是生成一種透鏡,即AccountEmailAccountPassphrase等。是否可以通過這種方式將它們組合在一起,而不一定是組合,而是說字符串連接,所以我經常發現自己正在編寫以下類型的函數:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM