“类型变量不明确”在 Haskell Yesod 中使用 Persistent

Posted

技术标签:

【中文标题】“类型变量不明确”在 Haskell Yesod 中使用 Persistent【英文标题】:"Type variable is ambiguous" with Persistent in Haskell Yesod 【发布时间】:2013-12-11 06:31:38 【问题描述】:

我正在尝试将 Persistent 与 Yesod 一起使用,以从我的数据库中的表中获取所有字段键的列表。我的访问器代码如下:

getMapList :: Handler [Text]
getMapList = runDB $ do
  dbList <- selectList [] []
  return (map getMapName dbList)
  where getMapName (Entity (Key (PersistText mapName)) _)  = mapName

注意这是一个游戏:这里的“地图”是游戏意义上的地图,而不是 Haskell 意义上的地图。

我收到以下错误,这表明类型推断引擎无法根据我使用的数据库后端确定我的类型。

Handler/Create.hs:101:13:
Couldn't match type `PersistEntityBackend t0'
              with `persistent-1.2.3.0:Database.Persist.Sql.Types.SqlBackend'
The type variable `t0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Expected type: PersistMonadBackend (SqlPersistT (HandlerT App IO))
  Actual type: PersistEntityBackend t0
In a stmt of a 'do' block: dbList <- selectList [] []
In the second argument of `($)', namely
  `do  dbList <- selectList [] [];
        return (map getMapName dbList) '
In the expression:
  runDB
  $ do  dbList <- selectList [] [];
         return (map getMapName dbList) 

有人知道如何解决这个问题吗?我需要在类型签名中添加什么才能正确地进行类型检查?谢谢!

编辑:我的模型是这样定义的:

GameMap
    mapName Text
    mapCode Text
    UniqueGameMap mapName
    deriving Typeable

【问题讨论】:

【参考方案1】:

我认为您需要添加过滤器类型签名,该签名基于您在其他地方定义的表(我不确定您是否试图避免在某处输入列名......我不确定如果可能的话)。

这对你有用吗?如果表定义为-

share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
KingsLadiesInWaiting
    name String
    skillLevel Int
    deriving Show
|]

只需添加-

getMapList :: Handler [T.Text]
getMapList = runDB $ do
  dbList <- selectList ([]::[Filter (KingsLadiesInWaitingGeneric backend)]) []
  return (map getMapName dbList)
  where getMapName (Entity (Key (PersistText mapName)) _)  = mapName

当我这样做时,它编译了。

这应该是一个有趣的游戏!

【讨论】:

我尝试使用 GameMapGeneric 而不是 KingsLadiesInWaitingGenerc,但出现以下错误:不在范围内:类型构造函数或类“GameMapGeneric”。有什么特别需要我进口的吗?我正在使用一个脚手架站点,所以我把它分散在一堆文件中,我的处理程序都在他们自己的文件中。 当您运行“yesod init”时,它应该已经创建了一个名为Model.hs 的文件,您需要将该文件与该函数一起导入到该文件中。实际模型应该在 config/models 中,因此您还可以验证“GameMap”表是否存在。 我仍然收到错误,当我执行“导入模型(GameMapGeneric)”时,我得到“模块'模型'不导出'GameMapGeneric'”。有什么想法吗?非常感谢到目前为止的所有帮助。 好/坏消息....好消息是 - 我使用“ghc --show-iface Model.hi”检查了 Model.hs 创建的数据类型,并能够找到创建的实际类型(它只是表名,末尾没有 Generic 一词)。它跑了。坏消息是,输出不是您预期的那样。它不是列名,而是列值。我可能会再玩一些,并尝试寻找是否有其他方法来获取列名。 搞定了,这有点小技巧,但我在选择过滤器列表中添加了一个微不足道的条件,而不是 [],这足以让类型检查器弄清楚。

以上是关于“类型变量不明确”在 Haskell Yesod 中使用 Persistent的主要内容,如果未能解决你的问题,请参考以下文章

Haskell:Yesod 和 Esqueleto

Haskell语言学习笔记(69)Yesod

Haskell,Yesod和Keter - 我如何定期(每5分钟)运行一次例行程序?

当用户不在 Yesod/Haskell 的数据库中时如何重定向到特殊页面

Haskell Yesod - 执行 POST 请求时浏览器 OPTIONS 请求的 CORS 问题

Yesod中的复合主键