Let's say I want to create a complex data structure consisting of multiple mutually recursive data types, with multiple type variables, and some functions to operate on those 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
Is there a way I can bundle the x y z
types, giving them a single name t
, and pluck out the x
, y
, or z
types when I actually need them? I don't want to proliferate x y z
throughout my data and function type declarations since adding an additional parameter could affect a lot of code.
i.e.
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
I don't know how to define the GetX
, GetY
, and GetZ
type 'functions' to extract the component types from the bundle.