【问题标题】:Haskell Beam code only works in one moduleHaskell Beam 代码仅适用于一个模块
【发布时间】:2020-05-13 12:07:12
【问题描述】:

我在这样的Schema 模块中定义了DatasourceId

import qualified Database.Beam as B

data DatasourceT f = Datasource
  { _datasourceId :: B.C f Text 
  , _datasourceName :: B.C f Text 
  } deriving (Generic, B.Beamable)

instance B.Table DatasourceT where
  data PrimaryKey DatasourceT f = DatasourceId (B.C f Text) deriving (Generic, B.Beamable)
  primaryKey = DatasourceId . _datasourceId

type DatasourceId = B.PrimaryKey DatasourceT Identity

但我无法在 Schema 模块之外使用它

(B.val_ $ DatasourceId $ _datasourceId d)

因为编译器会抱怨

>     • Data constructor not in scope:
>         DatasourceId :: t0 -> B.PrimaryKey DatasourceT Identity
>     • Perhaps you meant 'Datasource' (imported from Schema)
>     |
> 229 |  (B.val_ $ DatasourceId $ _datasourceId d)

虽然我有

import Schema (ControlAccessDb(..), Datasource, DatasourceId, DatasourceT(..))

那么有什么建议可以防止代码注定要被整合到一个模块中吗?这可能是类型家庭的怪癖吗? 看来问题出在

instance B.Table DatasourceT where
  data PrimaryKey DatasourceT f = DatasourceId (B.C f Text) deriving (Generic, B.Beamable)
  primaryKey = DatasourceId . _datasourceId

只有定义模块知道实例化内部。

请注意,Beam 文档本身也有这种用法(文档中嵌入的代码)。请参阅https://tathougies.github.io/beam/user-guide/manipulation/insert/,其中CustomerId 定义在https://github.com/tathougies/beam/blob/d87120b58373df53f075d92ce12037a98ca709ab/beam-sqlite/examples/Chinook/Schema.hs#L119

【问题讨论】:

    标签: haskell haskell-beam


    【解决方案1】:

    这是一种有点不直观的情况,发生在任何使用附加类型的地方,而不是特定于 Beam。

    因为DatasouceId 是附加类型PrimaryKey 的构造函数,所以您需要导出和导入该类型,就像使用普通的非附加类型一样。这有点不直观,因为 PrimaryKey 最初并未在您的模块中定义。但从某种意义上说,它是:您正在定义该类型的实例,因此您也可以导出它。我想这一定是这背后有争议的逻辑。

    像这样从您的Schema 模块导出:

    module Schema( ..., B.PrimaryKey(..), ... ) where
    

    像这样在需要的地方导入:

    import Schema(PrimaryKey(..))
    

    【讨论】:

    • 导出应该是合格的,所以我想你的意思是module Schema( ..., B.PrimaryKey(..), ... ) where
    • 是的,你是对的:在你的情况下,由于 Database.Beam.Schema 被导入为合格的,你也应该引用 PrimaryKey 的资格。我已经更新了答案。
    • 如果我有多个类型同义词,例如 type D2Id = B.PrimaryKey D2T Identity ,您的方法是否仍然有效?
    • “工作”以什么方式?
    • Table 是一个类,而 PrimaryKey 是一个附加类型。这大致意味着“Table 的每个实例都必须附加一些PrimaryKey 的定义”。您正在定义两者。您将PrimaryKey 的实例定义为data 类型,其中有一个名为DatasourceId 的构造函数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-16
    • 1970-01-01
    • 2020-09-16
    • 2023-03-30
    • 1970-01-01
    • 2019-11-01
    相关资源
    最近更新 更多