-1

I was wondering if there is an easy way to get the difference between 2 data types in Haskell, in a list of tuples.

Let's says I define 2 data types :

type Name = String
type Age = String
type Color = String
type Size = Int 

data Animal = Animal Name Age Color Size
data Cat = Cat Name Age Color

Then, I want to get a list of tuples containing all the animals but the cats. The function would be something like :

getAnimalsButCats :: [Animal] -> [Cat] -> [(Name, Age, Color)]
getAnimalsButCats [(Animal name age color _)] [(Cat nameC ageC colorC)] = //diff between [Animal] and [Cat]
Caro
  • 21
  • 7
  • There is no generic concept of a "diff" between ADTs. There is no formal relationship between `Animal` and `Cat` that you can exploit. Also, you clearly expected the `Name` constructor to be the `Name` type in your definitions of `Animal` and `Cat`, but it is not. In fact, duplicating this `Name` data constructor is not allowed within the same module scope and would have caused an error if you had attempted to compile your code. – Rein Henrichs Mar 15 '16 at 19:00
  • In `data Animal = Name Age Color Size` and `data Cat = Name Age Color`, `Name` is not the type synonym `type Name = String` defined above. Its syntactic position makes it the *data constructor* for the `Animal` and `Cat` ADTs. Multiple declarations of this `Name` constructor in the same scope are not allowed. You probably meant something like `data Animal = MkAnimal Name Age Color Size` (where `MkAnimal` is the constructor) instead, and likewise for `Cat`. – Rein Henrichs Mar 15 '16 at 19:07
  • @ReinHenrichs Ok you're right, thanks ! I will edit my post. – Caro Mar 15 '16 at 19:07
  • @ReinHenrichs Is there a concept of "diff" between tuples ? Could I create two tuples from those two ADT, and then do the diff between them? – Caro Mar 15 '16 at 19:21
  • Given that `[Animal]` cannot contain a value of type `Cat`, the trivial solution is `getAnimalsButCats animals = animals`. You need to redefine your `Animal` type to something like `Cat Name Age Color Size | Dog Name Age Color Size | ...`. – chepner Mar 15 '16 at 19:23
  • @chepner Got it ! But I was trying to avoid redefining the DTA's. – Caro Mar 15 '16 at 19:26
  • That's unavoidable, because right now there is *no way* for an `[Animal]` to contain a `Cat`. `Animal` and `Cat` are two completely different types. – chepner Mar 15 '16 at 19:30
  • @chepner Ok thanks, I understand. But could I create, with 2 additional functions, 2 lists of tuples both having the same format `[(Name, Age, Color)]` and then get the difference between those two ? – Caro Mar 15 '16 at 19:36

1 Answers1

0

You probably want something like

type Name = String
type Age = String
type Color = String
type Size = Int

data AnimalKind = Cat | Dog | Horse | Bird
data Animal = Animal AnimalKind Name Age Color Size

getAnimalsButCats :: [Animal] -> [(Name, Age, Color)]
getAnimalsButCats [] = []
-- Skip cats
getAnimalsButCats ((Animal Cat _ _ _ _):xs) = getAnimalsButCats xs
-- Save name, age, color for any other animal
getAnimalsButCats ((Animal _ name age color _): xs) = (name, age, color) : (getAnimalsButCats xs)
chepner
  • 389,128
  • 51
  • 403
  • 529