I am building a small DSL for iOS' autolayout feature. Obviously I want to have a typesafe way to define autolayouts instead of doing VSL. I came up with the following:
//in reality this will be a Xamarin/iOS View
type View =
| View
type Constraint =
| Max of int
| Min of int
| Eq of int
| Both of int * int
type Element =
| Gap of Constraint
| Part of View * Constraint
let horizontal superview : Element list = []
let max v = Max v
let min v = Min v
let eq v = Eq v
let minmax min max = Both(min, max)
let gap c es = Gap c :: es
let view v c es = Part (v, c) :: es
//transform needs to implement the real autolayouting.
//not yet done
let transform es = List.rev es
let super_view, left_view, middle_view, right_view = View, View, View, View
horizontal super_view
|> gap (min 20)
|> view left_view (min 20)
|> gap (max 30)
|> view middle_view (eq 45)
|> gap (eq 50)
|> view right_view (minmax 20 100)
|> gap (max 0)
|> transform
I am sort of content with the design so far; for example, it has a pretty "fluid" touch to it. However I am asking myself if there are better ways to do it.
One particular issue is the simple fact that every definition is a intersection of "gaps" and "views" starting with a "gap" and ending with a "gap". Is there a possibility to "encode" such a design into types instead of doing it via runtime exceptions (which I would do now).