3 ms·
This discussion here and Dhall's Github Readme seemed promising, so I went through the tutorial. I've recently had to write a lot of YAML like language with cus
by jarpineh 8y ago
This discussion here and Dhall's Github Readme seemed promising, so I went through the tutorial. I've recently had to write a lot of YAML like language with custom templating (think Ansible), so naturally I felt there was a way out with Dhall. I was hoping the author could perhaps point me towards explanations to what I noticed bothering me by this (admittedly short) experience that left me puzzled.
I saw that lists can have only one type of elements without annotating their types. With type annotation list can have differently typed values, but only if each element is explicitly stated (note: this is my understanding that might not be correct) meaning there's no dynamic content in a list. In same vein a map of maps needs to have all its keys stated by type annotation.
To me this seems too restrictive since the structure of data gets lost in the more verbose annotations. Not to mention the work of writing this annotation or the functionality to produce the same. In TypeScript I'd write something like this { [string] : [ Number | String ] } and I'd have my string keyed object with values of lists containing numbers and strings. Having a language like Dhall to help with creation of correct configuration code seems really useful instead of this messy combination of declarative and template language. I would like to understand things that can get better by using such an type system.
- Gabriel439 8y agoDhall's lists are homogeneous lists, meaning that every element always has the same type of value. This is true whether or not you annotate list elements with a type or you annotate the list with a type. You only need to annotate the type of an empty list. Lists with at least one element don't require a type annotation because the type can be inferred from the type of that element. Dhall does not have buit-in support for homogeneous maps. Dhall does have statically typed heterogeneous records (i.e. something like `{ foo = Bool, bar = "ABC" }` which has type `{ foo : Bool, bar : Text }` for example). If you want to store different type of values in the same list you wrap them in a union. For example, if you want to store both `Text` values and `Natural` numbers in a list you would do: let union = constructors < Left : Natural | Right : Text > in [ union.Left 10, union.Right "ABC", union.Right "DEF", union.Left 4 ] The closest thing to a homogeneous map in Dhall is an association list of type `[ { mapKey : Text, mapValue : a } ]` but even that is still not an exact fit since it doesn't guarantee uniqueness of keys. However, Dhall's JSON/YAML integration does convert that automatically to a JSON/YAML homogeneous map (i.e. a JSON record where every field has the same type). In general, Dhall's JSON/YAML integration has several tricks and conventions that translate to weakly typed JSON idioms (such as homogeneous maps, omitting null values, and using tags).
- jarpineh 8y agoThank you for your response. This Left and Right declaration style was a new one for me. Also, homogeneous map wasn't exactly a familiar concept. I don't remember meeting these when learning TypeScript and dabbling with Elm. I fear I don't quite grasp the type structure here yet. I can go forward with my testing based on your example.
- KirinDave 8y agoBy the way, it's entirely fair game for you to create config/domain specific things and not simply (Left|Right) dichotomies. And by the way, TypeScript DOES have a form of Sum typing like that as of 2017! You can say something like this from the manual: type Shape = Square | Rectangle | Circle | Triangle; function area(s: Shape) { switch (s.kind) { case "square": return s.size * s.size; case "rectangle": return s.height * s.width; case "circle": return Math.PI * s.radius ** 2; } // should error here - we didn't handle case "triangle" } (You can see more about it here: https://www.typescriptlang.org/docs/handbook/advanced-types.html https://www.typescriptlang.org/docs/handbook/advanced-types...., search for "Discriminated Unions".) You can also make these ad-hoc ,and they're useful for harnessing underlying functions that might return null from stdlibs. E.g., function strToInt( x: string ): number | null And then you're required to check for nulls and the compiler will complain if you don't check for them. Pretty useful!