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 }