One of the reasons we might want to pick an existential type is that it lets us (or the users of our library) compose a theme using a number of different colors of different types.
In your example, you have two different calls to `someFunc` that are each eventually converting two different colors, so you might say something like:
In this sort of situation there's not a strong difference between the two. There are a few other situations that, if we expect to encounter them, tip us in favor of considering existentials though. The big one from an API design standpoint is that your approach makes it a bit more work to allow the user to mix-and-match colors from different encodings.
If you think about the `ThemeInstance` in the article, it's a `Map String SomeColor`. If you wanted to eliminate the existential type you'd probably end up with something like:
Now you can case match against the constructors in `SomeColor` if you want:
myFunc someColor = case someColor of
SomeRGBColor rgb -> someFunc rgb
SomeCMYKColor cmyk -> someFun (cmykToRGB cmyk)
But if this is library code, you've now created a closed encoding- meaning that a user who wants to work with YUV or HSL or some esoteric encoding can't do it.
At the end of the day, it is a design decision. If you opt not to go with existentials and typeclasses you'll end up with a different sort of API with different benefits and limitations.
In your example, you have two different calls to `someFunc` that are each eventually converting two different colors, so you might say something like:
In this sort of situation there's not a strong difference between the two. There are a few other situations that, if we expect to encounter them, tip us in favor of considering existentials though. The big one from an API design standpoint is that your approach makes it a bit more work to allow the user to mix-and-match colors from different encodings.If you think about the `ThemeInstance` in the article, it's a `Map String SomeColor`. If you wanted to eliminate the existential type you'd probably end up with something like:
So you can have a `ThemeInstance RGB` or a `ThemeInstance CYMK`, but the user isn't allowed to freely mix-and-match.Of course, you could use an ADT rather than an existential type here:
Now you can case match against the constructors in `SomeColor` if you want: But if this is library code, you've now created a closed encoding- meaning that a user who wants to work with YUV or HSL or some esoteric encoding can't do it.At the end of the day, it is a design decision. If you opt not to go with existentials and typeclasses you'll end up with a different sort of API with different benefits and limitations.