Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do store algebraic data type in persistent

For a data type like so

data Tree = Node String Tree Tree
          | Leaf String

And real data like so

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

How do I store that into database using persistent, specifically how to do the "OR" part?

I've tried defining the model like so

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

The recursive structure would be stored in a column in a row as a json string automatically which is very nice. But how do we or can we define a "OR" structure in the persistent model?

like image 800
HHC Avatar asked Feb 27 '14 02:02

HHC


1 Answers

Persistent can only store ADTs that have no child data. I.E. the following can be stored:

data Tag = Leaf | Fork

But recursive structures like this cannot be stored without serialising it to JSON:

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

What you have to understand is that Persistent is a type save layer over the top of a database, so you have to think about your schema in terms of what is efficient to store in a database, not in terms of what's a convenient Haskell datastructure.

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

This schema will give you the equivalent of the following structure.

data Tree a = Value a [Tree a]
like image 93
Thomas Avatar answered Oct 19 '22 05:10

Thomas