4 ms·
Dhall'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
by Gabriel439 8y ago
Dhall'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!