Search code examples
databasehaskellmodelhaskell-persistent

Haskell "persistent" model: How to correctly define cross-reference?


Imagine you have two models (Foo and Bar) and they are both have references to each other (Foo have barRef with type BarId and Bar have fooRef with type FooId). Everything goes okay:

#!/usr/bin/env stack
{- stack script --resolver=lts-9.21 --package=persistent-template -}
{-# LANGUAGE GADTs, GeneralizedNewtypeDeriving, QuasiQuotes, TemplateHaskell #-}
{-# LANGUAGE TypeFamilies, MultiParamTypeClasses #-}

import Database.Persist.TH

mkPersist sqlSettings [persistLowerCase|
Foo
  barModel BarId
  fooField Int

Bar
  fooModel FooId
  barField Int
|]

main = pure ()

But if I wrap reference type to Maybe (just an example, it could Vector or anything else):

#!/usr/bin/env stack
{- stack script --resolver=lts-9.21 --package=persistent-template -}
{-# LANGUAGE GADTs, GeneralizedNewtypeDeriving, QuasiQuotes, TemplateHaskell #-}
{-# LANGUAGE TypeFamilies, MultiParamTypeClasses #-}

import Database.Persist.TH

mkPersist sqlSettings [persistLowerCase|
Foo
  barModel (Maybe BarId)
  fooField Int

Bar
  fooModel FooId
  barField Int
|]

main = pure ()

It fails with this error:

Not in scope: type constructor or class ‘BarId’

How I am supposed to solve this?


Solution

  • The syntax you are using for the Bar model isn't right. Something like this should work:

    #!/usr/bin/env stack
    -- stack script --resolver lts-12.7
    
    {-# LANGUAGE GADTs, GeneralizedNewtypeDeriving, QuasiQuotes, TemplateHaskell #-}
    {-# LANGUAGE TypeFamilies, MultiParamTypeClasses #-}
    
    import Database.Persist.TH
    
    mkPersist sqlSettings [persistLowerCase|
    Foo
      barModel BarId Maybe
      fooField Int
    
    Bar
      fooModel FooId
      barField Int
    |]
    
    main = pure ()
    

    See the official docs for reference.