繁体   English   中英

具有提取器类型功能的复合类型

[英]Composite type with extractor type functions

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

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

有没有一种方法可以捆绑xyz类型,给它们一个单一的名称t ,并在实际需要它们时拔出xyz类型? 我不想在整个数据和函数类型声明中扩散xyz ,因为添加其他参数可能会影响很多代码。

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

我不知道如何定义GetXGetYGetZ类型的“函数”以从包中提取组件类型。

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

如果您有一个具体的示例,我可以提供更具体的建议,但是通常最好的做法是继续使用参数,否则,我们将找出一种抽象出这三种类型之间关系的方法,从而只需要一个完全指定其他参数的参数(而不只是将其作为所讨论类型的列表)。

仍然,这是一个如何使用类型族来实现的示例:

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

从本质上讲,这等效于类型级lambda。

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

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

当然,除了tFoo是翻转的。

无论如何,Haskell没有真正的类型级lambda。 但是您可能想查看以下相关问题的答案: Laskda中Haskell中的类型表达式?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM