Hole Data Types

So, if I have two types of data that are basically the same, I can write them like this:

data A t = A1 | A2 | A3 | A4 (B t)
data B t = B1 | B2 | B3 | B4 t

type AX = A X
type AY = A Y

Now it's easy to write functions over AX and AY, or “A t,” if they don't care. But how can I write a conversion?

convert :: AX -> AY
convert (A4 (B4 x)) = A4 (B4 (xToY x))
convert ax = ay -- type error

So, now I need to write all the other cases manually, although none of them depends on the type parameter. To make matters worse, although I can match the constructor without depending on the arguments using "A {}", this is not possible if I need these arguments to recover the data.

Is there a better way to do this? I feel that GADT should be able to express this, but it's hard to figure out how to remove a type variable from terms that are independent of it. I think that I will have to have separate types for A1 A2, etc., and then I will lose the closedness and check of the check ... In addition, I do not want to write Show, Eq and Typeable manually! The only other way I can think of is to rebuild the entire structure in order to isolate the changing part, i.e.

data A t = Independent | B4 t
data Independent = A1 | A2 | ...

But this makes any other use of data inconvenient in the interests of a single conversion function.

Of course, another option is to forget about type safety and turn on “B4 (or XY)” and add some good runtime errors when it has the wrong value.

, " " ?

: , -fmap:

convert :: (a -> b) -> A a -> A b

, , -. , TH , , . , . , - , -, , , - .

+5
1

, , A B Functor s. , Haskell Functor , -XDeriveFunctor. :

data A t = A1 | A2 | A3 | A4 (B t) deriving Functor
data B t = B1 | B2 | B3 | B4 t deriving Functor

...

convert :: AX -> AY
convert a = fmap xToY a

GHCi- X, Y xToY, Show:

*Main> convert $ A4 B1
A4 B1
*Main> convert $ A4 (B4 X)
A4 (B4 Y)
*Main> convert $ A2
A2

Update

, A B X Y, :

class XorY t where

instance XorY X
instance XorY Y

data XorY t => A t = A1 | A2 | A3 | A4 (B t)
data XorY t => B t = B1 | B2 | B3 | B4 t

, A B Functor s, , , .

+2

All Articles