我应该如何在haskell中用constrant表示一个相互递归的数据类型?
我自己不太清楚,所以如果我的描述也不够清楚,请让我知道 所以,我有两门课:我应该如何在haskell中用constrant表示一个相互递归的数据类型?,haskell,Haskell,我自己不太清楚,所以如果我的描述也不够清楚,请让我知道 所以,我有两门课: class Prop1 a b | a -> b class Prop2 c d | c -> d 和数据类型: data X y z 它们之间的关系是: X是z的容器,其中y作为辅助容器 容器y应包含另一组实例X y z y满足Prop1,即以下条件: 实例属性1 y(X y z) X本身满足Prop2,因此: 实例Prop2(X y z)z 因此,当我定义X的实例时,我觉得自己陷入了一片混乱,我写了如
class Prop1 a b | a -> b
class Prop2 c d | c -> d
和数据类型:
data X y z
它们之间的关系是:
X
是z
的容器,其中y
作为辅助容器y
应包含另一组实例X y z
y
满足Prop1
,即以下条件:
实例属性1 y(X y z)
X
本身满足Prop2
,因此:
实例Prop2(X y z)z
X
的实例时,我觉得自己陷入了一片混乱,我写了如下内容:
instance Prop1 y (X y z) => Prop2 (X y z) z
但GHC似乎对此并不满意,并要求我添加
FlexibleContexts
和不可判定实例
,这让我感到不安全
我读到对数据设置约束并不好,但我尝试了,但没有帮助:
data Prop1 y (X y z) => X y z
我应该如何在Haskell中处理它?不可判定实例
使用起来是安全的,它只是意味着编译器不知道它将能够终止类型检查/解析约束。不可判定实例的最坏结果是编译器无法终止。我们可以看到编译器通过完成一个示例程序而终止
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE UndecidableInstances #-}
class Prop1 a b | a -> b
class Prop2 c d | c -> d
data X y z = X
instance Prop1 y (X y z) => Prop2 (X y z) z
-- An example Y and checking Prop2
data Y = Y
instance Prop1 Y (X Y ())
main :: Prop2 (X Y ()) () => IO ()
main = print "checked"
对于Prop1 Y x
实例,我们必须为z
选择具体类型;本质上,y
决定了z
。我选择了()
作为Y
;可能还有另一个Y'
具有不同的z
类型族
如果您不想使用不可判定实例
,可以使用类型族
而不是功能相关性
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
class Prop1 a where
type B a :: *
class Prop2 c where
type D c :: *
data X y z = X
instance (Prop1 y, B y ~ (X y z)) => Prop2 (X y z) where
type D (X y z) = z
-- An example Y and get the compiler to run all the way to requiring FlexibleContexts
data Y = Y
instance Prop1 Y where
type B Y = X Y ()
main :: Prop2 (X Y ()) => IO ()
main = print "checked"
UndedictableInstances
可以安全使用,它只是意味着编译器不知道它将能够终止类型检查/解析约束。不可判定实例的最坏结果是编译器无法终止。我们可以看到编译器通过完成一个示例程序而终止
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE UndecidableInstances #-}
class Prop1 a b | a -> b
class Prop2 c d | c -> d
data X y z = X
instance Prop1 y (X y z) => Prop2 (X y z) z
-- An example Y and checking Prop2
data Y = Y
instance Prop1 Y (X Y ())
main :: Prop2 (X Y ()) () => IO ()
main = print "checked"
对于Prop1 Y x
实例,我们必须为z
选择具体类型;本质上,y
决定了z
。我选择了()
作为Y
;可能还有另一个Y'
具有不同的z
类型族
如果您不想使用不可判定实例
,可以使用类型族
而不是功能相关性
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
class Prop1 a where
type B a :: *
class Prop2 c where
type D c :: *
data X y z = X
instance (Prop1 y, B y ~ (X y z)) => Prop2 (X y z) where
type D (X y z) = z
-- An example Y and get the compiler to run all the way to requiring FlexibleContexts
data Y = Y
instance Prop1 Y where
type B Y = X Y ()
main :: Prop2 (X Y ()) => IO ()
main = print "checked"
不是我不想用的。我只是不清楚那是什么。具体来说,它是否安全。你能再解释一下吗?我也不知道你的代码是如何工作的不可判定实例
是安全的,它只是意味着编译器不知道它将能够终止类型检查/解析约束。不可判定实例的最坏结果是编译器无法终止。听起来不错。已添加到我的“确定使用”列表中。@hustmphrr:不过我同意。这不是我不想使用的。我只是不清楚那是什么。具体来说,它是否安全。你能再解释一下吗?我也不知道你的代码是如何工作的不可判定实例
是安全的,它只是意味着编译器不知道它将能够终止类型检查/解析约束。不可判定实例的最坏结果是编译器无法终止。听起来不错。已添加到我的“可以使用”列表中。@hustmphrr:不过我同意。我还不确定我是否了解所有内容。例如,您说“容器y
应包含另一组实例xyz
”,但您计划如何确保这一点?为什么要以您建议的方式限制Prop2(X y z)z
实例?(对我来说这看起来很荒谬——事实上,instance prop1y(X y z)
已经看起来很荒谬了。)简言之:你到底想做什么?我和下一个家伙一样喜欢一个好的抽象问题;但这一个闻起来很像一个X/Y问题,所以我鼓励你们尽可能多地包含你们觉得合适的实践/激励细节,包括。@DanielWagner我正在haskell中探索数据结构引导。理论上应该这样定义类型。我非常确定这不是一个xy问题,因为这是我在实现过程中遇到的问题。“Y是我在X的实现过程中遇到的问题”基本上是对X/Y问题如何产生的定义——符合要求所需要的就是避免完全谈论X,就像你在这个问题中所做的那样。一定要包括关于什么是数据结构引导的详细信息,它的用途,以及您试图用它做什么。我不确定我是否了解所有内容。例如,您说“容器y
应包含另一组实例xyz
”,但您计划如何确保这一点?为什么要以您建议的方式限制Prop2(X y z)z
实例?(对我来说这看起来很荒谬——事实上,instance prop1y(X y z)
已经看起来很荒谬了。)简言之:你到底想做什么?我和下一个家伙一样喜欢一个好的抽象问题;但这一个闻起来很像一个X/Y问题,所以我鼓励你们尽可能多地包含你们觉得合适的实践/激励细节,包括。@DanielWagner我正在haskell中探索数据结构引导。理论上应该这样定义类型。我非常确定这不是一个xy问题,因为这是我在实现过程中遇到的问题。“Y是我在实现X时遇到的问题”几乎是X/Y问题如何产生的定义——都是t