Возможно ли повторное использование GHCJS кода, сгенерированного Template Haskell?

В этот момент GHCJS не удается скомпилировать postgresql-simple пакет (см. [1]). Я хочу использовать пакет persistent для создания моделей БД. Интересно, можно ли компилировать модели с помощью самого GHC и повторно использовать код, сгенерированный Template Haskell, в исходниках GHCJS?


У меня уже есть обходной путь для моей проблемы, но вопрос все еще актуален. Я оставлю его открытым на несколько дней, и если никто не ответит, как использовать код, сгенерированный с помощью Template Haskell, я закрою его. Я вставил полученный код внизу.

ОБНОВЛЕНИЕ:
thomie предложил мне флаг -dth-dec-file, который можно записать как языковую прагму в файле моделей, например. {-# OPTIONS_GHC -dth-dec-file #-}. Затем после запуска команды stack build в папке .stack-work/dist/<arch>/<cabal-version>/build/src появится файл Model.th.hs. Этот файл выглядит как действительный Haskell, однако GHC отклоняет его из-за ошибки синтаксического анализа (см. код внизу). Однако я нашел способ скомпилировать модель с помощью GHCJS. Я добавил условие в файл Cabal для удаления postgresql-simple из зависимостей:

-- project.cabal
library
  -- ...
  if impl(ghcjs)
    build-depends:       persistent
                       , persistent-template
  else
    build-depends:       persistent
                       , persistent-postgresql
                       , persistent-template
                       , postgresql-simple

Код, сгенерированный Template Haskell (чтобы протестировать этот код, я скопировал этот файл в исходную папку проекта и добавил объявление модуля вверху)

-- src/Model.hs:(16,1)-(17,54): Splicing declarations
instance Database.Persist.Class.PersistField.PersistField Manufacturer where
  Database.Persist.Class.PersistField.toPersistValue
    = \ ent_a9ov
        -> (Database.Persist.Types.Base.PersistMap
            GHC.Base.$
              (GHC.List.zip
                 (GHC.Base.map Data.Text.pack ["name"])
                 ((GHC.Base.map Database.Persist.Class.PersistField.toPersistValue)
                  GHC.Base.$
                    (Database.Persist.Class.PersistEntity.toPersistFields ent_a9ov))))
  Database.Persist.Class.PersistField.fromPersistValue
    = ((\ x_a9ow
          -> let columns_a9ox = Data.HashMap.Strict.fromList x_a9ow
             in
               (Database.Persist.Class.PersistEntity.fromPersistValues
                GHC.Base.$
                  ((GHC.Base.map
                      (\ name_a9oy
                         -> case
                                Data.HashMap.Base.lookup (Data.Text.pack name_a9oy) columns_a9ox
                            of {
                              GHC.Base.Just v_a9oz -> v_a9oz
                              GHC.Base.Nothing -> Database.Persist.Types.Base.PersistNull }))
                   GHC.Base.$ ["name"])))
       Control.Monad.<=<
         Database.Persist.Class.PersistField.getPersistMap)
instance Database.Persist.Sql.Class.PersistFieldSql Manufacturer where
  Database.Persist.Sql.Class.sqlType _
    = Database.Persist.Types.Base.SqlString
data Manufacturer
  = Manufacturer {manufacturerName :: !Text}
  deriving (Show, Read, Typeable)
type ManufacturerId =
    Database.Persist.Class.PersistEntity.Key Manufacturer
instance Database.Persist.Class.PersistEntity.PersistEntity Manufacturer where
  type Database.Persist.Class.PersistEntity.PersistEntityBackend Manufacturer = Database.Persist.Sql.Types.SqlBackend
  data Database.Persist.Class.PersistEntity.Unique Manufacturer
    = UniqueManufacturer Text
  newtype Database.Persist.Class.PersistEntity.Key Manufacturer
    = ManufacturerKey {unManufacturerKey :: Database.Persist.Class.PersistStore.BackendKey Database.Persist.Sql.Types.SqlBackend}
    deriving (GHC.Show.Show,
              GHC.Read.Read,
              GHC.Classes.Eq,
              GHC.Classes.Ord,
              Web.PathPieces.PathPiece,
              Web.HttpApiData.Internal.ToHttpApiData,
              Web.HttpApiData.Internal.FromHttpApiData,
              Database.Persist.Class.PersistField.PersistField,
              Database.Persist.Sql.Class.PersistFieldSql,
              Data.Aeson.Types.Class.ToJSON,
              Data.Aeson.Types.Class.FromJSON)
  data Database.Persist.Class.PersistEntity.EntityField Manufacturer typ
    = typ ~ Database.Persist.Class.PersistEntity.Key Manufacturer =>
      ManufacturerId |
      typ ~ Text => ManufacturerName
  Database.Persist.Class.PersistEntity.keyToValues
    = ((GHC.Types.: [])
       GHC.Base..
         (Database.Persist.Class.PersistField.toPersistValue
          GHC.Base.. unManufacturerKey))
  Database.Persist.Class.PersistEntity.keyFromValues
    = ((GHC.Base.fmap ManufacturerKey)
       GHC.Base..
         (Database.Persist.Class.PersistField.fromPersistValue
          GHC.Base.. Database.Persist.TH.headNote))
  Database.Persist.Class.PersistEntity.entityDef _
    = Database.Persist.Types.Base.EntityDef
        (Database.Persist.Types.Base.HaskellName
           (Database.Persist.TH.packPTH "Manufacturer"))
        (Database.Persist.Types.Base.DBName
           (Database.Persist.TH.packPTH "manufacturer"))
        (Database.Persist.Types.Base.FieldDef
           (Database.Persist.Types.Base.HaskellName
              (Database.Persist.TH.packPTH "Id"))
           (Database.Persist.Types.Base.DBName
              (Database.Persist.TH.packPTH "id"))
           (Database.Persist.Types.Base.FTTypeCon
              GHC.Base.Nothing (Database.Persist.TH.packPTH "ManufacturerId"))
           Database.Persist.Types.Base.SqlInt64
           []
           GHC.Types.True
           (Database.Persist.Types.Base.ForeignRef
              (Database.Persist.Types.Base.HaskellName
                 (Database.Persist.TH.packPTH "Manufacturer"))
              (Database.Persist.Types.Base.FTTypeCon
                 (GHC.Base.Just (Database.Persist.TH.packPTH "Data.Int"))
                 (Database.Persist.TH.packPTH "Int64"))))
        [Database.Persist.TH.packPTH "json"]
        [Database.Persist.Types.Base.FieldDef
           (Database.Persist.Types.Base.HaskellName
              (Database.Persist.TH.packPTH "name"))
           (Database.Persist.Types.Base.DBName
              (Database.Persist.TH.packPTH "name"))
           (Database.Persist.Types.Base.FTTypeCon
              GHC.Base.Nothing (Database.Persist.TH.packPTH "Text"))
           Database.Persist.Types.Base.SqlString
           []
           GHC.Types.True
           Database.Persist.Types.Base.NoReference]
        [Database.Persist.Types.Base.UniqueDef
           (Database.Persist.Types.Base.HaskellName
              (Database.Persist.TH.packPTH "UniqueManufacturer"))
           (Database.Persist.Types.Base.DBName
              (Database.Persist.TH.packPTH "unique_manufacturer"))
           [(Database.Persist.Types.Base.HaskellName
               (Database.Persist.TH.packPTH "name"), 
             Database.Persist.Types.Base.DBName
               (Database.Persist.TH.packPTH "name"))]
           []]
        []
        [Database.Persist.TH.packPTH "Show",
         Database.Persist.TH.packPTH "Read",
         Database.Persist.TH.packPTH "Typeable"]
        (Data.Map.Base.fromList [])
        GHC.Types.False
  Database.Persist.Class.PersistEntity.toPersistFields
    (Manufacturer x_a9oA)
    = [Database.Persist.Class.PersistField.SomePersistField x_a9oA]
  Database.Persist.Class.PersistEntity.fromPersistValues [x1_a9oC]
    = Manufacturer
      Data.Functor.<$>
        ((Database.Persist.TH.mapLeft
            (Database.Persist.TH.fieldError
               (Database.Persist.TH.packPTH "name")))
         GHC.Base.. Database.Persist.Class.PersistField.fromPersistValue)
          x1_a9oC
  Database.Persist.Class.PersistEntity.fromPersistValues x_a9oB
    = (Data.Either.Left
       GHC.Base.$
         (GHC.Base.mappend
            (Database.Persist.TH.packPTH
               "Manufacturer: fromPersistValues failed on: ")
            (Data.Text.pack GHC.Base.$ (GHC.Show.show x_a9oB))))
  Database.Persist.Class.PersistEntity.persistUniqueToFieldNames
    (UniqueManufacturer {})
    = [(Database.Persist.Types.Base.HaskellName
          (Database.Persist.TH.packPTH "name"), 
        Database.Persist.Types.Base.DBName
          (Database.Persist.TH.packPTH "name"))]
  Database.Persist.Class.PersistEntity.persistUniqueToValues
    (UniqueManufacturer x_a9oD)
    = [Database.Persist.Class.PersistField.toPersistValue x_a9oD]
  Database.Persist.Class.PersistEntity.persistUniqueKeys
    (Manufacturer _name_a9oE)
    = [UniqueManufacturer _name_a9oE]
  Database.Persist.Class.PersistEntity.persistFieldDef ManufacturerId
    = Database.Persist.Types.Base.FieldDef
        (Database.Persist.Types.Base.HaskellName
           (Database.Persist.TH.packPTH "Id"))
        (Database.Persist.Types.Base.DBName
           (Database.Persist.TH.packPTH "id"))
        (Database.Persist.Types.Base.FTTypeCon
           GHC.Base.Nothing (Database.Persist.TH.packPTH "ManufacturerId"))
        Database.Persist.Types.Base.SqlInt64
        []
        GHC.Types.True
        (Database.Persist.Types.Base.ForeignRef
           (Database.Persist.Types.Base.HaskellName
              (Database.Persist.TH.packPTH "Manufacturer"))
           (Database.Persist.Types.Base.FTTypeCon
              (GHC.Base.Just (Database.Persist.TH.packPTH "Data.Int"))
              (Database.Persist.TH.packPTH "Int64")))
  Database.Persist.Class.PersistEntity.persistFieldDef
    ManufacturerName
    = Database.Persist.Types.Base.FieldDef
        (Database.Persist.Types.Base.HaskellName
           (Database.Persist.TH.packPTH "name"))
        (Database.Persist.Types.Base.DBName
           (Database.Persist.TH.packPTH "name"))
        (Database.Persist.Types.Base.FTTypeCon
           GHC.Base.Nothing (Database.Persist.TH.packPTH "Text"))
        Database.Persist.Types.Base.SqlString
        []
        GHC.Types.True
        Database.Persist.Types.Base.NoReference
  Database.Persist.Class.PersistEntity.persistIdField
    = ManufacturerId
  Database.Persist.Class.PersistEntity.fieldLens ManufacturerId
    = Database.Persist.TH.lensPTH
        Database.Persist.Class.PersistEntity.entityKey
        (\ (Database.Persist.Class.PersistEntity.Entity _ value_a9oF)
           key_a9oG
           -> Database.Persist.Class.PersistEntity.Entity key_a9oG value_a9oF)
  Database.Persist.Class.PersistEntity.fieldLens ManufacturerName
    = Database.Persist.TH.lensPTH
        (manufacturerName
         GHC.Base.. Database.Persist.Class.PersistEntity.entityVal)
        (\ (Database.Persist.Class.PersistEntity.Entity key_a9oH
                                                        value_a9oI)
           x_a9oJ
           -> Database.Persist.Class.PersistEntity.Entity
                key_a9oH (value_a9oI {manufacturerName = x_a9oJ}))
instance Database.Persist.Class.PersistStore.ToBackendKey Database.Persist.Sql.Types.SqlBackend Manufacturer where
  Database.Persist.Class.PersistStore.toBackendKey
    = unManufacturerKey
  Database.Persist.Class.PersistStore.fromBackendKey
    = ManufacturerKey
instance Data.Aeson.Types.Class.ToJSON Manufacturer where
  Data.Aeson.Types.Class.toJSON (Manufacturer name_a9oL)
    = Data.Aeson.Types.Internal.object
        [((Data.Text.pack "name") Data.Aeson.Types.Instances..= name_a9oL)]
instance Data.Aeson.Types.Class.FromJSON Manufacturer where
  Data.Aeson.Types.Class.parseJSON
    (Data.Aeson.Types.Internal.Object obj_a9oK)
    = ((GHC.Base.pure Manufacturer)
       GHC.Base.<*>
         (obj_a9oK Data.Aeson.Types.Instances..: (Data.Text.pack "name")))
  Data.Aeson.Types.Class.parseJSON _ = GHC.Base.mzero
instance Data.Aeson.Types.Class.ToJSON (Database.Persist.Class.PersistEntity.Entity Manufacturer) where
  Data.Aeson.Types.Class.toJSON
    = Database.Persist.Class.PersistEntity.entityIdToJSON
instance Data.Aeson.Types.Class.FromJSON (Database.Persist.Class.PersistEntity.Entity Manufacturer) where
  Data.Aeson.Types.Class.parseJSON
    = Database.Persist.Class.PersistEntity.entityIdFromJSON
migrateAll :: Database.Persist.Sql.Types.Migration
migrateAll
  = do { let defs_a9oM
               = [Database.Persist.Types.Base.EntityDef
                    (Database.Persist.Types.Base.HaskellName
                       (Database.Persist.TH.packPTH "Manufacturer"))
                    (Database.Persist.Types.Base.DBName
                       (Database.Persist.TH.packPTH "manufacturer"))
                    (Database.Persist.Types.Base.FieldDef
                       (Database.Persist.Types.Base.HaskellName
                          (Database.Persist.TH.packPTH "Id"))
                       (Database.Persist.Types.Base.DBName
                          (Database.Persist.TH.packPTH "id"))
                       (Database.Persist.Types.Base.FTTypeCon
                          GHC.Base.Nothing (Database.Persist.TH.packPTH "ManufacturerId"))
                       Database.Persist.Types.Base.SqlInt64
                       []
                       GHC.Types.True
                       (Database.Persist.Types.Base.ForeignRef
                          (Database.Persist.Types.Base.HaskellName
                             (Database.Persist.TH.packPTH "Manufacturer"))
                          (Database.Persist.Types.Base.FTTypeCon
                             (GHC.Base.Just (Database.Persist.TH.packPTH "Data.Int"))
                             (Database.Persist.TH.packPTH "Int64"))))
                    [Database.Persist.TH.packPTH "json"]
                    [Database.Persist.Types.Base.FieldDef
                       (Database.Persist.Types.Base.HaskellName
                          (Database.Persist.TH.packPTH "name"))
                       (Database.Persist.Types.Base.DBName
                          (Database.Persist.TH.packPTH "name"))
                       (Database.Persist.Types.Base.FTTypeCon
                          GHC.Base.Nothing (Database.Persist.TH.packPTH "Text"))
                       Database.Persist.Types.Base.SqlString
                       []
                       GHC.Types.True
                       Database.Persist.Types.Base.NoReference]
                    [Database.Persist.Types.Base.UniqueDef
                       (Database.Persist.Types.Base.HaskellName
                          (Database.Persist.TH.packPTH "UniqueManufacturer"))
                       (Database.Persist.Types.Base.DBName
                          (Database.Persist.TH.packPTH "unique_manufacturer"))
                       [(Database.Persist.Types.Base.HaskellName
                           (Database.Persist.TH.packPTH "name"), 
                         Database.Persist.Types.Base.DBName
                           (Database.Persist.TH.packPTH "name"))]
                       []]
                    []
                    [Database.Persist.TH.packPTH "Show",
                     Database.Persist.TH.packPTH "Read",
                     Database.Persist.TH.packPTH "Typeable"]
                    (Data.Map.Base.fromList [])
                    GHC.Types.False];
         Database.Persist.Sql.Migration.migrate
           defs_a9oM
           (Database.Persist.Types.Base.EntityDef
              (Database.Persist.Types.Base.HaskellName
                 (Database.Persist.TH.packPTH "Manufacturer"))
              (Database.Persist.Types.Base.DBName
                 (Database.Persist.TH.packPTH "manufacturer"))
              (Database.Persist.Types.Base.FieldDef
                 (Database.Persist.Types.Base.HaskellName
                    (Database.Persist.TH.packPTH "Id"))
                 (Database.Persist.Types.Base.DBName
                    (Database.Persist.TH.packPTH "id"))
                 (Database.Persist.Types.Base.FTTypeCon
                    GHC.Base.Nothing (Database.Persist.TH.packPTH "ManufacturerId"))
                 Database.Persist.Types.Base.SqlInt64
                 []
                 GHC.Types.True
                 (Database.Persist.Types.Base.ForeignRef
                    (Database.Persist.Types.Base.HaskellName
                       (Database.Persist.TH.packPTH "Manufacturer"))
                    (Database.Persist.Types.Base.FTTypeCon
                       (GHC.Base.Just (Database.Persist.TH.packPTH "Data.Int"))
                       (Database.Persist.TH.packPTH "Int64"))))
              [Database.Persist.TH.packPTH "json"]
              [Database.Persist.Types.Base.FieldDef
                 (Database.Persist.Types.Base.HaskellName
                    (Database.Persist.TH.packPTH "name"))
                 (Database.Persist.Types.Base.DBName
                    (Database.Persist.TH.packPTH "name"))
                 (Database.Persist.Types.Base.FTTypeCon
                    GHC.Base.Nothing (Database.Persist.TH.packPTH "Text"))
                 Database.Persist.Types.Base.SqlString
                 []
                 GHC.Types.True
                 Database.Persist.Types.Base.NoReference]
              [Database.Persist.Types.Base.UniqueDef
                 (Database.Persist.Types.Base.HaskellName
                    (Database.Persist.TH.packPTH "UniqueManufacturer"))
                 (Database.Persist.Types.Base.DBName
                    (Database.Persist.TH.packPTH "unique_manufacturer"))
                 [(Database.Persist.Types.Base.HaskellName
                     (Database.Persist.TH.packPTH "name"), 
                   Database.Persist.Types.Base.DBName
                     (Database.Persist.TH.packPTH "name"))]
                 []]
              []
              [Database.Persist.TH.packPTH "Show",
               Database.Persist.TH.packPTH "Read",
               Database.Persist.TH.packPTH "Typeable"]
              (Data.Map.Base.fromList [])
              GHC.Types.False) }

Сообщение об ошибке сообщило об ошибке синтаксического анализа в -> в строке, начинающейся с GHC.Base.Nothing ->

(\ name_a9oy
     -> case
            Data.HashMap.Base.lookup (Data.Text.pack name_a9oy) columns_a9ox
        of {
          GHC.Base.Just v_a9oz -> v_a9oz
          GHC.Base.Nothing -> Database.Persist.Types.Base.PersistNull }))

person Geradlus_RU    schedule 11.06.2016    source источник


Ответы (1)


РЕДАКТИРОВАТЬ: вы не можете напрямую повторно использовать код, сгенерированный в сборке ghc, но вы можете просто использовать модуль, содержащий вашу модель базы данных Persistent, в коде ghcjs. Это сгенерирует и создаст материал базы данных с помощью GHCJS, после чего он будет доступен для вашего кода GHCJS.

person Martin Vlk    schedule 12.06.2016
comment
Привет @Мартин Вик! Вы имеете в виду сборку модуля отдельно от всей библиотеки? - person Geradlus_RU; 12.06.2016
comment
Да, ваш подход работает, если я избегаю зависимости postgresql-simple для клиентского кода. - person Geradlus_RU; 28.06.2016