我应该如何在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