【问题标题】:Haskell Read type InferenceHaskell 读取类型推断
【发布时间】:2013-01-23 18:05:46
【问题描述】:

我已经编写了自己的基于邻接矩阵的图实现,并创建了Read 类的实例。

我的图表采用类型作为输入,这将是边的类型。

如果我尝试像这样的表达方式

read " - - 8 \n - 9 - \n 1 2 3" :: GraphADJ Int

它工作得很好(它是一个有 3 个节点的图,边从第一个节点到第三个节点,从第二个节点到第二个节点,从第三个节点到所有节点)。

我想要做的是不能告诉类型推断边缘的类型,而是将它们放入上下文中(如read"4"+3)。

我有函数insertEdge,它接受一个图、几个节点和新边。

insertEdge :: Graph g n e => g -> (n, n) -> e -> g

GraphGraphADJ 作为实例的图的通用类)

所以当我尝试做的时候

 insertEdge (read " - - 8 \n - 9 - \n 1 2 3" :: GraphADJ Int) (1,2) 3

它工作得很好,但如果我不明确类型,我会收到错误 Ambiguous type variables

我是否忘记了 Read 中的某些内容或遗漏了什么?

【问题讨论】:

  • 只是好奇,但你为什么不简单地deriving (Read) 并为自定义序列化格式使用单独的函数?
  • 我不太清楚你所说的“自定义序列化格式”是什么意思,反正我做了我的图实例 read 因为这是我的任务的一部分(现在结束了)。
  • 您的GraphADJ 类型是否也适用于Integer 参数,即read " - - 8 \n - 9 - \n 1 2 3" :: GraphADJ Integer 也可以使用?我猜是这样,你遇到了问题,因为 Haskell 中的数字文字是多态的。试试Characters 而不是数字!

标签: haskell type-inference typeclass


【解决方案1】:

问题是编译器没有足够的信息来推断读取类型。

即使您提供nInteInt 的类型信息,编译器仍然没有g 的信息。它只知道g 是一个带有Graph g Int Int 实例的类型。即使有单一类型存在于这样的实例中,它仍然无法推断出g

编译器无法自动看到在当前范围内只有这样的类型具有这样的实例,因为允许这样的行为可能会通过导入模块导致代码中断。

因此,解决方案是提供显式签名或制作insertEdge 的专用版本,提供显式具体类型来为read 提供足够的信息。如果您在多个地方将其用于同一类型,后者将很有用。

【讨论】:

  • 我对此表示怀疑,我也尝试过insertEdge (read " - - 8 \n - 9 - \n 1 2 3" ) (1,2) (3 :: Int),但我仍然遇到错误(我应该在主帖中发布,抱歉)
  • insertEdge (read " - - 8 \n - 9 - \n 1 2 3" ) (1 :: Int,2 ) (3 :: Int)insertEdge (read " - - 8 \n - 9 - \n 1 2 3" ) ((1,2) :: (Int,Int)) (3 :: Int) 仍然导致我进入 No instance for (Graph g0 Int Int) 我觉得我错过了一些理论背景。
  • @user1544128 简单地说,即使你给 Ints 一个显式类型,编译器也不可能猜到你想使用特定实现 GraphADJ,因为对 insertEdge 的调用适用于Graph 的任何实例。因此Graph g Int Int 中的g 仍然模棱两可。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多