Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6352521
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 24, 20262026-05-24T22:13:17+00:00 2026-05-24T22:13:17+00:00

So if I have two data types which are mostly the same, I can

  • 0

So if I have two data types which are mostly 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 then how do 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 out by hand, even though none of them depend on the type parameter. What’s worse, while I can match a constructor without depending on the arguments with ‘A {}’, that’s not possible if I need those arguments to reconstruct the data.

Is there a nicer way to do this? I feel like GADTs should be able to express this but it’s hard to see how to eliminate the type variable from the terms that don’t depend on it. I think I’d have to have separate types for A1 A2 etc. and then I’d lose the closed-ness and case checking… besides I don’t want to write Show, Eq, and Typeable by hand! The only other way I can think of is to rearrange the whole structure to isolate the changing part i.e.

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

But this makes every other use of the data awkward for the benefit of one conversion function.

Of course, yet another option is to forget about type safety and include ‘B4 (Either X Y)’ and put in some nice runtime errors for when it has the wrong value.

Maybe there’s a better way to approach “almost the same” data types?

Update: so I worked around by writing a pseudo-fmap:

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

Which at least allows me to separate the conversion part and the packing-unpacking boilerplate. I guess a sufficiently advanced bit of TH could probably generate one of those for me. I’m still curious about other approaches though. I feel like this way is still not precise, because it allows the hole to be filled with anything while what I really mean is exactly one of two things.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-24T22:13:18+00:00Added an answer on May 24, 2026 at 10:13 pm

    It seems like basically what you want is for A and B to be Functors. Fortunately, you can allow Haskell to derive the obvious Functor instances for these types, using -XDeriveFunctor. Then, use this code:

    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
    

    Here’s a sample GHCi session after adding some dummy definitions for X, Y and xToY, as well as having everything derive Show:

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

    Update

    If you really want to only allow A and B to be “filled” with things of type X or Y, you could constrain them like so:

    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
    

    Of course this will preclude the possibility of making A and B Functors, so the trick outlined above won’t work any more.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have a large tree-like data structure of objects which behave mostly identical but
So I have two custom complex types like this (oversimplified for this example): public
I have two data types, which are used for hastache templates. It makes sense
I have two arrays of System.Data.DataRow objects which I want to compare. The rows
I have two projects, the DLL project which has all my logic and data
I have a two-dimensional array (of Strings) which make up my data table (of
I have some logic, which defines and uses some user-defined types, like these: class
I have two sets of data which I need to join, but there is
I have two data structure classes (this is a simplified version of my code)
I have this structure which I want to write to a file: typedef struct

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.