GHCJS 是否可以重用模板生成的代码 Haskell

Is it possible GHCJS to reuse code generated by Template Haskell

此时 GHCJS 无法编译 postgresql-simple 包(参见 [1])。我想使用 persistent 包来生成数据库模型。我想知道是否可以使用 GHC 本身编译模型并在 GHCJS 源代码中重用模板 Haskell 生成的代码?


我的问题已经有了解决方法,但这个问题仍然相关。我会将其打开几天,如果没有人回答如何使用模板 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

模板生成的代码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 }))

编辑:您不能直接重用在 ghc 构建中生成的代码,但您可以简单地在 ghcjs 代码中使用包含持久数据库模型的模块。这将使用 GHCJS 生成和构建数据库内容,然后它可用于您的 GHCJS 代码。