Haskell读取类型推断

Haskell读取类型推断,haskell,type-inference,typeclass,Haskell,Type Inference,Typeclass,我自己编写了一个基于邻接矩阵的图的实现,并创建了Read类的实例 我的图形以一个类型作为输入,它将是边的类型 如果我试着像 read " - - 8 \n - 9 - \n 1 2 3" :: GraphADJ Int 它工作得很好(这是一个有3个节点的图,边从第一个节点到第三个节点,从第二个节点到第二个节点,从第三个节点到所有节点) 我想做的是不告诉类型推断边的类型,而是将它们放入上下文中(如read“4”+3) 我有一个函数insertEdge,它获取一个图、几个节点和新边 insertE

我自己编写了一个基于邻接矩阵的图的实现,并创建了
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
Graph
是图形的一般类,
GraphADJ
是该图形的实例)

所以当我试着去做

 insertEdge (read " - - 8 \n - 9 - \n 1 2 3" :: GraphADJ Int) (1,2) 3
它工作得很好,但是如果我不使类型显式,我会得到错误
不明确的类型变量


我是否在
读取过程中忘记了某些内容
或者我遗漏了一些内容?

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

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

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


因此,解决方案要么是提供明确的签名,要么是制作一个专门版本的
insertEdge
,提供明确的具体类型,为
read
提供足够的信息。如果在多个位置对同一类型使用后者,则后者将非常有用

我只是好奇,但为什么你不简单地
派生(读取)
并为自定义序列化格式使用单独的函数呢?我不太确定你所说的“自定义序列化格式”是什么意思,反正我制作了Read的图形实例,因为这是我作业的一部分(现在结束了)。您的
GraphADJ
类型是否对
Integer
参数也有意义,即
读取“--8\n-9-\n 1 2 3”::GraphADJ Integer
也有效?我猜是的,你会遇到问题,因为Haskell中的数字文字是多态的。尝试使用
Char
actors而不是数字!我考虑过这一点,我也尝试过
insertEdge(读“--8\n-9-\n123”)(1,2)(3::Int)
,但我还是遇到了一个错误(我应该在主帖子中发布,对不起)
insertEdge(读“--8\n-9-\n123”)(1::Int,2)(3::Int)
insertEdge(读“--8\n-9-\n123”)((1,2)::(Int,Int))(3::Int)
仍然导致我没有(图g0 Int)的实例我觉得我错过了一些理论背景。@user1544128简单地说,即使您给int指定了一个显式类型,编译器也不可能猜到您想要使用特定的实现
GraphADJ
,因为调用
insertEdge
可以处理
Graph
的任何实例de>g在
图g Int
中仍然不明确。