tkf*_*tkf 1 haskell instance typeclass
我试图制作一个简单的图形结构,我写了以下内容.但温室气体引起了错误,我堆积在那里.这是我第一次制作自己的类型类,所以也许我做的事情非常糟糕.有人可以解释什么是错的吗?
我发现了一个类似的问题,但我不认为它适用于我的情况: 在类型类的实例中错误绑定类型变量
class Link l where
node :: (Node n) => l -> n
class Node n where
links :: (Link l) => n -> [l]
data (Node n) => SimpleLink n =
SimpleLink
{ simpleLinkNode :: n
} deriving (Show, Read, Eq)
instance (Node n) => Link (SimpleLink n) where
node = simpleLinkNode
data (Link l) => SimpleNode l =
SimpleNode
{ simpleNodeLinks :: [l]
} deriving (Show, Read, Eq)
instance (Link l) => Node (SimpleNode l) where
links = simpleNodeLinks
Run Code Online (Sandbox Code Playgroud)
这是我收到的错误消息:
***.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
Run Code Online (Sandbox Code Playgroud)
得到:"`n'不适用于足够的类型参数"
class Link l n where
node :: Node n l => l n -> n l
class Node n l where
links :: Link l n => n l -> [l n]
Run Code Online (Sandbox Code Playgroud)
得到:"在类声明中循环(通过超类)"
class (Node n) => Link l n where
node :: l -> n
class (Link l) => Node n l where
links :: n -> [l]
Run Code Online (Sandbox Code Playgroud)
得到:"在类声明中循环(通过超类)"
class (Node n) => Link l n | l -> n where
node :: l -> n
class (Link l) => Node n l | n -> l where
links :: n -> [l]
Run Code Online (Sandbox Code Playgroud)
我想要实现的是一个有向无环图结构,如下所示(更具体地说,一个因子图).
PRML图8.51 http://research.microsoft.com/en-us/um/people/cmbishop/prml/prmlfigs-png/Figure8.51.png
有两种节点(白色圆圈和红色方块),它们只连接到不同类型的节点,这意味着有两种链接.
我想要不同版本的节点和链接,它们附有数据(数组).我也想要"vanilla"DAG,它只有一种类型的节点和链接.但是为了遍历它们,我只想要一个接口来做到这一点.
类方法的签名
class Link l where
node :: (Node n) => l -> n
class Node n where
links :: (Link l) => n -> [l]
Run Code Online (Sandbox Code Playgroud)
说,"无论何种类型的来电者的欲望,nodeRESP,links可以生产它,只要它的成员LinkRESP.Node",但执行说,只有一个有价值的特定类型的都可以生产.
它与OOP中的接口有根本的不同,OOP中的实现决定了类型,调用者必须接受它,这里调用者决定.
您正在遇到构造函数类尝试的问题.你的类需要两个参数,l那种kl和n种类kn.参数的种类(->)必须是*,类型的种类.因此,l n为了成为一个良好的论证(->),l必须是一个类型构造函数,采用类型的论证kn并创建一种类型的结果*,即
l :: kn -> *
Run Code Online (Sandbox Code Playgroud)
现在你尝试将结果类型node设为be n l,这意味着
n :: kl -> *
Run Code Online (Sandbox Code Playgroud)
但在上面我们看到了kl = kn -> *,产量
n :: (kn -> *) -> *
Run Code Online (Sandbox Code Playgroud)
RESP.kn = (kn -> *) -> *,这是一种无限的.无限类型,如无限类型,是不允许的.但那种推理只执行非常简陋,所以编译器假定参数l有样*,但看到从n l该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
Run Code Online (Sandbox Code Playgroud)
您必须DatatypeContexts从数据声明中删除,
然后上面的编译.不过,我认为它不会对你有所帮助.正如Chris Kuklewicz所说,你的类型追逐自己的尾巴,你会用它们作为
SimpleLink (SimpleNode (SimpleLink (SimpleNode ... {- ad infinitum -})))
Run Code Online (Sandbox Code Playgroud)
对于多参数类,如编译器所说,你不能让每个参与者都有一个需求导致一个依赖循环(同样,在你的约束中你只使用一个参数,
class Node n => Link l n where ...
Run Code Online (Sandbox Code Playgroud)
这是错误的,编译器会拒绝,如果周期被打破).
您可以通过合并类来解决周期,
class NodeLinks l n | l -> n, n -> l where
node :: l -> n
links :: n -> l
Run Code Online (Sandbox Code Playgroud)
但是你仍然有你的类型对它没用的问题.
抱歉,我不能很好地理解你的目标,建议一个可行的解决方案.