[英]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
,并在实际需要它们时拔出x
, y
或z
类型? 我不想在整个数据和函数类型声明中扩散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
我不知道如何定义GetX
, GetY
和GetZ
类型的“函数”以从包中提取组件类型。
您可以使用类型家族来做到这一点,但是几乎可以肯定这是过分的。 通常最好设计您的数据类型,以便将来不再需要任何其他参数。 当然,这非常接近于预测未来,但是如果有疑问,您应该添加参数而不是使用具体类型:)
如果您有一个具体的示例,我可以提供更具体的建议,但是通常最好的做法是继续使用参数,否则,我们将找出一种抽象出这三种类型之间关系的方法,从而只需要一个完全指定其他参数的参数(而不只是将其作为所讨论类型的列表)。
仍然,这是一个如何使用类型族来实现的示例:
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
当然,除了t
和Foo
是翻转的。
无论如何,Haskell没有真正的类型级lambda。 但是您可能想查看以下相关问题的答案: Laskda中Haskell中的类型表达式?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.