Can Standard ML express subtypes of datatypes?

279 Views Asked by At

Is there a way to have a subtype of a datatype in SML, such that the subtype would cover only some of the datatype's constructors? Something like this:

(* This works as expected *)
datatype Animal = Cat | Dog | Elephant | Zebra;

(* This overrides the Animal constructors instead of co-opting them *)
datatype Pet = Cat | Dog;

(* This causes a syntax error *)
type Pet = Cat | Dog;
1

There are 1 best solutions below

0
On BEST ANSWER

I'll add to @molbdnilo's answer: What you mean to say is, can datatype value constructors (Cat, Dog, etc.) be overloaded for multiple types? And the answer is no. This happens to be an uncommon feature in functional languages. Some functional languages feature some degree of overloading of values.

You could say that your Pet type is a subtype of Animal, as in values being a subset, even though SML does not operate with subtypes in this way. Your third attempt of type Pet = Cat | Dog is not possible because type is used for aliases which cannot have their own unique constructors, only refer to existing types rather than values such as Cat and Dog; datatype value constructors live in the domain of values, whereas types Pet and Animal live in the domain of types.

So one thing you can do instead is use parameterised value constructors:

type lives = int

datatype mammal = Cat of lives | Dog
datatype reptile = Turtle | Lizard
datatype fictive = Unicorn

datatype animal = Mammal of mammal
                | Reptile of reptile
                | Fictive of fictive

Now you have values Mammal (Cat 9), Reptile Turtle, Fictive Unicorn that all belong to the same type. I've used uppercase for value constructors and lowercase for type names just to make it clear what's what, even though this convention is not strictly enforced in SML.