具有提取器类型函数的复合类型

时间:2011-12-27 18:31:04

标签: haskell types

假设我想创建一个由多个相互递归数据类型组成的复杂数据结构,包含多个类型变量,以及一些对这些类型进行操作的函数:

data Foo x y z = FooA x | FooB (Bar x y z) | FooC (Foo x y z) | FooD (Baz x y z)
data Bar x y z = BarA y | BarB (Baz x y z) | BarC (Bar x y z) | BarD (Foo x y z)
data Baz x y z = BazA z | BazB (Foo x y z) | BazC (Baz x y z) | BazD (Bar x y z)

f :: Foo x y z -> Bar x y z -> Baz x y z
g :: Bar x y z -> Baz x y z -> Foo x y z

我是否可以捆绑x y z类型,为其指定一个名称t,然后选择xy或{{1}我真的需要它们的类型?我不想在我的数据和函数类型声明中扩散z,因为添加一个额外的参数可能会影响很多代码。

x y z

我不知道如何定义data Foo t = FooA (GetX t) | FooB (Bar t) | FooC (Foo t) | FooD (Baz t) data Bar t = BarA (GetY t) | BarB (Baz t) | BarC (Bar t) | BarD (Foo t) data Baz t = BazA (GetZ t) | BazB (Foo t) | BazC (Baz t) | BazD (Bar t) f :: Foo t -> Bar t -> Baz t g :: Bar t -> Baz t -> Foo t GetXGetY类型'函数'以从包中提取组件类型。

2 个答案:

答案 0 :(得分:1)

你可以用type families做到这一点,但这几乎肯定是矫枉过正;通常最好设计您的数据类型,以便将来不会需要任何其他参数。当然,这非常接近于预测未来,但如果有疑问,您应该添加一个参数而不是使用具体类型:)

如果你有一个具体的例子,我可以给出更具体的建议,但通常最好的办法就是继续使用这些参数,或者找出一种方法来抽象出这三种类型之间的关系,以便你只需要一个完全指定其他参数的参数(不要只是一个相关类型的列表)。

不过,这里有一个如何用类型系列实现它的例子:

type family GetX t
type instance GetX (a,b,c) = a

type family GetY t
type instance GetY (a,b,c) = b

type family GetZ t
type instance GetZ (a,b,c) = c

答案 1 :(得分:0)

这基本上相当于类型级别的lambda。

type t = (\f -> f x y z)

t Foo --> (\f -> f x y z) Foo --> Foo x y z

当然,tFoo会被翻转。

无论如何,Haskell没有真正的类型级lambdas。但您可能想查看相关问题的答案:Lambda for type expressions in Haskell?