1

I need to describe in Standard-ML a language made of properties and values. My property system is made of properties which can have values, like for example:

color: red | yellow | blue | transparent
align: left | center | right
bgcolor: red | yellow | blue | transparent

I created this sml file which tries to describe these properties:

datatype colorvalue = Transparent
                    | Yellow
                    | Blue
                    | Red

datatype bgcolorvalue = Transparent
                      | Yellow
                      | Blue
                      | Red

datatype alignvalue = Left
                    | Center
                    | Right

(* Generic property: it can be any of the above *)
datatype property = Color of colorvalue
                  | BgColor of bgcolorvalue
                  | Align of alignvalue

(* Some values *)
val prop1: property = Color   Transparent
val prop2: property = BgColor Transparent

When I compile this in MoscowML I get:

,File "c:\Users\myuser\documents\myproj\property.sml", line 21, characters 31-42:
! val prop1: property = Color   Transparent
!                               ^^^^^^^^^^^
! Type clash: expression of type
!   bgcolorvalue
! cannot have type
!   colorvalue

My guess

So I think that the problem is that color and bgcolor share a common property value: transparent which reflects in datatypes colorvalue and bgcolorvalue to share constructor Transparent. Actually they share all values, thus all constructors.

  • Is it the reason for this failure?
  • In any case, what should I do to describe my system?

1 Answer 1

6

It is easy to see that trying to use the same constructor in different types in the same scope would create problems with type inference. For example, what should the type of

fun heat Transparent = Yellow
|   heat Yellow = Red
|   heat Red = Blue
|   heat Blue = Blue;

be? colorvalue ->colorvalue or bgbcolorvalue -> bgbcolorvalue or colorvalue -> bgbcolorvalue or bgbcolorvalue -> colorvalue?

The easiest workaround would be to adopt different naming conventions for the constructors. You could also use structures (which is how SML keeps e.g. different uses of the name map in the basis library without any clashes). Something like:

structure Color = struct
    datatype value = Transparent
                   | Yellow
                   | Blue
                   | Red
end

structure BGBColor = struct
    datatype value = Transparent
                   | Yellow
                   | Blue
                   | Red
end;

Then you can do things like:

- val a = Color.Transparent;
val a = Transparent : Color.value

- val b = BGBColor.Transparent;
val b = Transparent : BGBColor.value

This last was run in the SML/NJ REPL and illustrates how there are now no clashes.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you John, had a feeling that structures could help me. I am gonna try this and tell you! I have only one question. In the question I have omitted the fact that I have those datatypes enclosed in a big structure. Are there any problems if I nest structures?
@Andry Try it and see. I've never had occasion to do so, though I don't anticipate that there would be any problem.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.