Skip to content

zz note: row optional polymorphic records

David Jeske edited this page May 31, 2020 · 7 revisions

One common reasons dynamic languages are preferred is handling external data heterogeneity without fighting with a static typechecker, as discussed somewhat in zz-node: heterogeneous lists of maps.

One narrow form of this is optionality, fields which may be optionally present or not.

  • optional function arguments - missing creates implicit default value
  • optional data elements in hetrogenous maps - present only when relevant, such as in JSON
  • optional nesting - recursive tree optionality (such as null pointers) are one such example

This note outlines some thoughts about making optionality more natural in Irken records. However, perhaps this is a half-way measure. Further more radical ideas are considered in zz note: blurring row typed records and JSON.

Row Optional Polymorphic Records

The idea is to specify certain fields as optional, and then allow their types to match records which do or do not contain those fields. Optional fields would merge into any open record specification as optional fields for the type. An optional and non-optional occurrence of a field unify into an optional occurrence of the field.

(list { a=1 b?=2 } { a=1 c?=3 } { a=1 b=1 } ) : (list { a=int b?=int c?=int ... })

Accesses to optional fields would have to match some known optional field, and would be an error if the optional field was never a part of the type. Normally, accessing an optional field would produce a maybe type:

(match rec.b with 
   (maybe:yes value) -> (handle-b value)
   (maybe:no)        -> (handle-b-missing))

Alternatively, pattern matching could be used to directly test for the field presence:

(match rec with { a=a ... } -> (handle-a a))
(match rec with { b=b ... } -> (handle-b b))
(match rec with { c=c ... } -> (handle-c c))

Example Use Case : hiccup

One example use case is libraries like Clojure Hiccup. This allows the creation of html documents from data-structures, or data-structures from html documents. In Irken such a facility can be type-checked, but expressing them can be cumbersome with explicit variant option types like Maybe. Here are some examples of hiccup data forms in Clojure:

(html (:a { href="http://www.foo.com" } "Link Text" ))
(html (:a { href="http://www.foo.com" target="_blank"} "Link Text")) 
(html (:div { id="email" class="selected starred"} "Div Content")

In Irken, with some form of natural record field optionality, it might be natural to express and typecheck these types of data inside Irken. For example, a document dataset might be constructed with variants and records that look something like this:

(:html {} 
   (:head {} (list))
   (:body {} (list
     (:text "Some body text")
     (:a { href = "http://www.foo.com" } "Linked Text")
     (:div { class="bar" } 
         (:div {} (:text "Nested Div"))
     )
   )
)

It would be nice to be able to allow the user to extend the valid tags and attributes that an html-from-data system accepts, but to do this seems like it would require running code in the compiler.

Example Use Case: JSON Data

JSON maps routinely contain optional fields. These are cumbersome to represent in current Irken. However, with optional fields, they become easy.

[  { "Name" : "David", "Email" : "foo@foo.com" },
   { "Name" : "Fred" } ]

The type of this data in Irken would be:

(list { Name = string Email? = string })