【问题标题】:How to do store algebraic data type in persistent如何在持久化中存储代数数据类型
【发布时间】:2014-03-30 06:16:17
【问题描述】:

对于这样的数据类型

data Tree = Node String Tree Tree
          | Leaf String

还有像这样的真实数据

my_tree = (Node "first node" (Leaf "leaf") (Node "second node" (Leaf "leaf") (Leaf "leaf")))

如何使用持久性将其存储到数据库中,特别是如何执行“OR”部分?

我试过这样定义模型

share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
    Tree
        value String
        leftTree Leaf
        rightTree Leaf
        deriving Show
    Leaf
        value String
        deriving Show
|]

递归结构会自动作为json字符串存储在一行中的列中,这非常好。但是我们如何或者可以在持久模型中定义一个“OR”结构呢?

【问题讨论】:

  • 如果您的问题需要存储如此复杂的数据,也许使用酸态会更方便?
  • 同上。我正在尝试将reffit 从酸状态迁移到持久以节省内存。作为 SQL 的新手,我对实际进入数据库的类型的紧缩感到惊讶。我不得不把我所有的列表类型的记录字段都“翻过来”。

标签: haskell yesod persistent


【解决方案1】:

Persistent 只能存储没有子数据的 ADT。 IE。可以存储以下内容:

data Tag = Leaf | Fork

但是如果不将其序列化为 JSON,就无法存储像这样的递归结构:

data Tree a = (Leaf a) | Fork (Tree a) (Tree a)

您必须了解的是 Persistent 是数据库顶部的类型保存层,因此您必须根据在数据库中存储的效率而不是方便的方式来考虑架构Haskell 数据结构。

share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
    Tree
        parent TreeId Maybe
        value String
        deriving Show
|]

此架构将为您提供以下结构的等价物。

data Tree a = Value a [Tree a]

【讨论】:

  • 你的意思是“没有递归子数据”吗?所以例如data Tag = Leaf Int | Fork String可以存储吗?
  • @AlexeyRomanov,你知道,我从未尝试过。我敢打赌它实际上可以被存储,尽管它需要首先以某种方式进行序列化,而且我已经有一段时间没有查看持久代码的那部分了。
  • 是的....我最终明白它只是数据库的一层。我只是想知道,因为它足够聪明,可以将其更改为 json,它还可以帮助保持带有“OR”的数据类型的结构吗?如果是这样如何在模型中定义它?或者就像你写的那样,树是可能的,叶子会一直在那里?
  • 另外,parent TreeId Maybe 是如何转换为可能的树列表的?
  • @HCC 这是一个反向关系,这意味着许多 Tree 行可以引用父 Tree 行。因此,当将其编写为 ADT 并将其表示为前向关系时,我们将其表示为树列表。试想一下,每个节点只能有一个父节点,但可以有多个子节点。
猜你喜欢
  • 1970-01-01
  • 2011-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多