gpt4 book ai didi

database - Haskell 存储具有持久定义的组合 ADT

转载 作者:搜寻专家 更新时间:2023-10-30 23:40:54 25 4
gpt4 key购买 nike

我如何创建类似于此 ADTYesod Persistent 实体:

import Data.Ratio

data Work = Work { name :: String
, payment :: WorkPayment
, duration :: WorkDuration }

data WorkPayment = WorkPaymentUndefined
| WorkPaymentEstimated { workPaymentEstimatedUnity :: TemporalUnity
, workPaymentEstimatedValue :: Ratio Int }
| WorkPaymentTotal { workPaymentTotalValue :: Ratio Int }

data WorkDuration = WorkDurationUndefined
| WorkDurationEstimated { workDurationEstimatedUnity :: TemporalUnity
, workDurationEstimatedQuantity :: Int }
| WorkDurationPermanent

data TemporalUnity = Hour | Day | Week | Month

长名称可以通过使用单独的模块来避免,但我更喜欢在这个例子中将它们放在一起。

对于简单的枚举,它看起来很简单,但我无法弄清楚在这种情况下表将如何,就像在关系数据库(如 MySQL)中一样

最佳答案

要使用 Persistent 存储 ADT,您只需告诉 Persistent 如何从数据库中序列化/反序列化该值。为此,将其设为 PersistField 的实例(将其转换为基本类型,如 TextByteString)和 PersistFieldSql(指定要使用的数据库列的类型)。

关于(反)序列化数据,您有多种选择。我想编码/解码为二进制值会更快,但我推荐 JSON,因为:

  • 它在数据库级别是人类可读的
  • 一些数据库内置了对它的支持
  • 它是可移植的
  • 通过 to/fromPersistValueJSON 将支持内置到 Persistent 中。

举个例子:

-- Add this extension to derive To/FromJSON instances; see Data.Aeson for details
{-# LANGUAGE DeriveGeneric #-}

module Models.Work where

import Database.Persist.Sql (PersistFieldSql(..))
import ClassyPrelude.Yesod
import Data.Aeson

data TemporalUnity = Hour | Day | Week | Month deriving (Generic)

instance FromJSON TemporalUnity
instance ToJSON TemporalUnity

data WorkDuration = WorkDurationUndefined
| WorkDurationEstimated { workDurationEstimatedUnity :: TemporalUnity
, workDurationEstimatedQuantity :: Int }
| WorkDurationPermanent deriving (Generic)

instance FromJSON WorkDuration
instance ToJSON WorkDuration

-- Store the values as as SqlString. The actual column type will be dependent on the database backend. SqlString will be something like varchar/text types.
-- You can also use PersistByteString, which might be faster
instance PersistFieldSql WorkDuration where
sqlType _ = SqlString


instance PersistField WorkDuration where
toPersistValue = toPersistValueJSON
fromPersistValue = fromPersistValueJSON

这是从 Postgres 中选择的样子:

foo=# SELECT * FROM "user";
id | ident | password | duration
----+--------+----------+-------------------------------------------------------------------------------------------------------
5 | foo123 | | {"tag":"WorkDurationPermanent","contents":[]}
6 | bar456 | | {"tag":"WorkDurationEstimated","workDurationEstimatedQuantity":1,"workDurationEstimatedUnity":"Hour"}

我不太熟悉 MySQL 或 Postgres 中的原生 JSON 支持,但如果您想基于底层 JSON 数据进行查询,您可能需要研究一下。

关于database - Haskell 存储具有持久定义的组合 ADT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35465354/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com