Mapping Tagged Union types to other languages?

As Math

type Content
  = Text { uuid : String , title : String }
  | Markdown { uuid : String , markdown : String }
  | Figure { uuid : String , markdown : String , title : String , imageId : Maybe String }

is equivalent to the expression:

uuid * title + uuid * markdown + uuid * markdown * title * imageId

taking the common factor

=  uuid * (title + markdown + markdown * title * imageId)

Which converted back into Elm gives me an equivalent data model:

type alias Content =
  { uuid : String
  , contentType : ContentType
  }

type ContentType
  = Text { title : String }
  | Markdown { markdown : String }
  | Figure { markdown : String, title : String, imageId : String }

I could also have taken the common factor markdown out of Markdown and Figure, but that seems to be going too far.

I just like that the normal rules of math let you manipulate data models as refactoring rules.

Given that a type can be written out as a sum-of-products by applying the multiplications over all the bracketed sums, it seems likely that it would be possible to prove that any type can always be made only 2 levels deep, as a simple sum-of-products. That is, so long as the type does not recurse. I can apply this ‘theorem’ to my Content type by explicitly multiplying out the Maybe in imageId, like this:

    uuid * title + uuid * markdown + uuid * markdown * title * imageId
  = uuid * title + uuid * markdown + uuid * markdown * title * (int + empty)
  = uuid * title + uuid * markdown + uuid * markdown * title * int + uuid * markdown * title * empty

  and taking empty = 0
  
  = uuid * title + uuid * markdown + uuid * markdown * title * int + uuid * markdown * title

Which suggests that a simpler way of building my Content model might be:

type Content
  = Text { uuid : String , title : String }
  | Markdown { uuid : String , markdown : String }
  | Figure { uuid : String , markdown : String , title : String , imageId : String }
  | Caption { uuid : String , markdown : String , title : String }
2 Likes