Haskell 正在尝试创建我的typeclass/实例。GHC说:“这是一个很好的例子;无法推断……”;
我试图制作一个简单的图形结构,我写了以下内容。但温室气体引起了错误,我把它堆积在那里。这是我第一次制作自己的typeclass,所以也许我做错了什么。有人能解释一下怎么回事吗 我发现了一个类似的问题,但我认为它不适用于我的情况 这是我收到的错误消息:Haskell 正在尝试创建我的typeclass/实例。GHC说:“这是一个很好的例子;无法推断……”;,haskell,instance,typeclass,Haskell,Instance,Typeclass,我试图制作一个简单的图形结构,我写了以下内容。但温室气体引起了错误,我把它堆积在那里。这是我第一次制作自己的typeclass,所以也许我做错了什么。有人能解释一下怎么回事吗 我发现了一个类似的问题,但我认为它不适用于我的情况 这是我收到的错误消息: ***.hs:13:10:Could not deduce (n ~ n1) from the context (Node n) bound by the instance declaration at ***.hs:12:10-40 o
***.hs:13:10:Could not deduce (n ~ n1)
from the context (Node n)
bound by the instance declaration
at ***.hs:12:10-40
or from (Node n1)
bound by the type signature for
node :: Node n1 => SimpleLink n -> n1
at ***.hs:13:3-23
`n' is a rigid type variable bound by
the instance declaration
at ***.hs:12:16
`n1' is a rigid type variable bound by
the type signature for node :: Node n1 => SimpleLink n -> n1
at ***.hs:13:3
Expected type: SimpleLink n -> n1
Actual type: SimpleLink n -> n
In the expression: simpleLinkNode
In an equation for `node': node = simpleLinkNode
***.hs:21:11:Could not deduce (l ~ l1)
from the context (Link l)
bound by the instance declaration
at ***.hs:20:10-40
or from (Link l1)
bound by the type signature for
links :: Link l1 => SimpleNode l -> [l1]
at ***.hs:21:3-25
`l' is a rigid type variable bound by
the instance declaration
at ***.hs:20:16
`l1' is a rigid type variable bound by
the type signature for links :: Link l1 => SimpleNode l -> [l1]
at ***.hs:21:3
Expected type: SimpleNode l -> [l1]
Actual type: SimpleNode l -> [l]
In the expression: simpleNodeLinks
In an equation for `links': links = simpleNodeLinks
编辑1
我试了一些。
但我不能让它们工作
构造函数类
Get:“'n'未应用于足够的类型参数”
多参数类型类(MPTC)
Got:“类内循环声明(通过超类)”
具有函数依赖关系的MPTC
Got:“类内循环声明(通过超类)”
目标(编辑2)
我想要实现的是一个有向无环图结构,如下所示(更具体地说,a)
(来源:) 有两种节点(白色圆圈和红色正方形),它们只连接到不同类型的节点,这意味着有两种链接
我想要不同版本的节点和链接,这些节点和链接上连接有数据(数组)。我还想要“香草”DAG,它只有一种类型的节点和链接。但是为了遍历它们,我只需要一个接口就可以了。类方法的签名
class Link l where
node :: (Node n) => l -> n
class Node n where
links :: (Link l) => n -> [l]
假设“调用方想要的任何类型,节点
响应链接都可以生成它,只要它是链接
响应节点的成员”,但实现说只能生成一种特定类型的值
它与OOP中的接口有根本的不同,在OOP中,实现决定类型,调用方必须接受类型,这里由调用方决定
您的构造函数类尝试遇到了一些问题。你的类有两个参数,
l
类的kl
和n
类的kn
。(>)
的参数类型必须同时为*
,即类型类型。因此,要使ln
成为(>)
的一个类型良好的参数,l
必须是一个类型构造函数,它接受一个kn
类型的参数,并创建一个*
类型的结果,即
l :: kn -> *
现在您尝试将节点的结果类型设置为nl
,这意味着
n :: kl -> *
但在上面我们看到,kl=kn->*
,这会产生
n :: (kn -> *) -> *
分别kn=(kn->*)->*
,这是一种无限类型。与无限类型一样,无限类型是不允许的。但是种类推断的实现非常简单,因此编译器假定l
的参数具有种类*
,但从nl
中可以看出n
具有种类kl->*
,因此作为l
的参数,n
具有错误的种类,它没有应用于足够的类型参数
构造函数类的正常使用是单参数类
class Link l where
node :: l nod -> nod
class Node n where
links :: n lin -> [lin]
-- note that we don't have constraints here, because the kinds don't fit
instance Link SimpleLink where
node = simpleLinkNode
instance Node SimpleNode where
links = simpleNodeLinks
您必须从数据声明中删除DatatypeContexts
它们已从语言中删除(可通过扩展提供)
反正也没用
然后进行上述编译。不过,我认为这对你没什么帮助。正如Chris Kuklewicz所观察到的,你的类型追逐他们自己的尾巴,你会把他们当作
SimpleLink (SimpleNode (SimpleLink (SimpleNode ... {- ad infinitum -})))
对于多参数类,您不能像编译器所说的那样,让每个类都有另一个的需求,这会导致依赖循环(同样,在约束中,您只能将它们与一个参数一起使用
class Node n => Link l n where ...
这是不正确的,编译器将拒绝(如果循环被破坏)
你可以通过合并类来解决这个循环
class NodeLinks l n | l -> n, n -> l where
node :: l -> n
links :: n -> l
但是您仍然会遇到这样的问题:您的类型在这方面没有用处
对不起,我不太了解您的目标,无法提出可行的解决方案。类方法的签名
class Link l where
node :: (Node n) => l -> n
class Node n where
links :: (Link l) => n -> [l]
假设“调用方想要的任何类型,节点
响应
链接都可以生成它,只要它是链接
响应节点的成员”,但实现说只能生成一种特定类型的值
它与OOP中的接口有根本的不同,在OOP中,实现决定类型,调用方必须接受类型,这里由调用方决定
您的构造函数类尝试遇到了一些问题。你的类有两个参数,
l
类的kl
和n
类的kn
。(>)
的参数类型必须同时为*
,即类型类型。因此,要使ln
成为(>)
的一个类型良好的参数,l
必须是一个类型构造函数,它接受一个kn
类型的参数,并创建一个*
类型的结果,即
l :: kn -> *
现在您尝试将节点的结果类型设置为nl
,这意味着
n :: kl -> *
但在上面我们看到,kl=kn->*
,这会产生
n :: (kn -> *) -> *
分别kn=(kn->*)->*
,这是一种无限类型。与无限类型一样,无限类型是不允许的。但是种类推断的实现非常简单,因此编译器假定l
的参数具有种类*
,但从nl
中可以看出n
具有种类kl->*
,因此作为l
的参数,n
具有错误的种类,它没有应用于足够的类型参数
构造函数类的正常使用是单参数类
class Link l where
node :: l nod -> nod
class Node n where
links :: n lin -> [lin]
-- note that we don't have constraints here, because the kinds don't fit
instance Link SimpleLink where
node = simpleLinkNode
instance Node SimpleNode where
links = simpleNodeLinks
您必须从数据声明中删除DatatypeContexts
它们已从语言中删除(可通过扩展提供)
反正也没用
然后进行上述编译。不过,我认为这对你没什么帮助。正如Chris Kuklewicz所观察到的,你的类型追逐他们自己的尾巴,你会把他们当作
SimpleLink (SimpleNode (SimpleLink (SimpleNode ... {- ad infinitum -})))
对于多路径
class Link l where
node :: (Node n) => l -> n
instance (Node n) => Link (SimpleLink n) where
node = simpleLinkNode
`n' is a rigid type variable bound by
the instance declaration
at ***.hs:12:16
`n1' is a rigid type variable bound by
the type signature for node :: Node n1 => SimpleLink n -> n1
at ***.hs:13:3
-- Bipartite graph representation, unlabeled edges
-- Data types to hold information about nodes, e.g. ID number
data VariableVertex = VV { vvID :: Int } deriving (Show)
data FactorVertex = FV { fvID :: Int } deriving (Show)
-- Node holds itself and a list of neighbors of the oppostite type
data Node selfType adjacentType =
N { self :: selfType
, adj :: [Node adjacentType selfType] }
-- A custom Show for Node to prevent infinite output
instance (Show a, Show b) => Show (Node a b) where
show (N x ys) = "Node "++ show x ++ " near " ++ show (map self ys)
-- Type aliases for the two node types that will be used
type VariableNode = Node VariableVertex FactorVertex
type FactorNode = Node FactorVertex VariableVertex
data FactorGraph = FG [VariableNode] [FactorNode] deriving (Show)
v1 = N (VV 1) [f1,f2]
v2 = N (VV 2) [f2]
v3 = N (VV 3) [f1,f3]
f1 = N (FV 1) [v1,v3]
f2 = N (FV 2) [v1,v2]
f3 = N (FV 3) [v3]
g = FG [v1,v2,v3] [f1,f2,f3]
class NodeClass n where
adjacent :: n a b -> [n b a]
data Node selfType adjacentType =
N
{ selfNode :: selfType
, adjNode :: [Node adjacentType selfType] }
data NodeWithData selfType adjacentType =
NWD
{ selfNodeWithData :: selfType
, adjNodeWithData :: [NodeWithData adjacentType selfType]
, getDataWithData :: [Double]
}
instance NodeClass Node where
adjacent = adjNode
instance NodeClass NodeWithData where
adjacent = adjNodeWithData
data VariableVertex = VV { vvID :: Int } deriving (Show)
data FactorVertex = FV { fvID :: Int } deriving (Show)
type VariableNode = Node VariableVertex FactorVertex
type FactorNode = Node FactorVertex VariableVertex
type VariableNodeWithData = NodeWithData VariableVertex FactorVertex
type FactorNodeWithData = NodeWithData FactorVertex VariableVertex