3 ms·
This looks like a typed take on KDB/Q, something that is long overdue! The key to making this work is structural typing of rows (row polymorphism / extensible r
by willtim 9y ago
This looks like a typed take on KDB/Q, something that is long overdue! The key to making this work is structural typing of rows (row polymorphism / extensible records). I'd be interested to see more details on how they tackled this.
- amiramir 9y agoMorgan Stanley has a history of languages in the vein. MS was a big APL shop in the 80s. Arthur Whitney[1] worked at MS and developed the languages A, and A+. He later wrote J, and K. [1] https://en.wikipedia.org/wiki/Arthur_Whitney_(computer_scientist) https://en.wikipedia.org/wiki/Arthur_Whitney_(computer_scien...
- throwaway7645 9y agoI think J was mainly written by Roger Hui (now @ Dyalog APL) after Ken Iverson designed it himself. I think Roger was inspired by Whitney though...or was Whitney actually involved?
- kthielen 9y agoYes, structural typing of records (and variants and recursives) has been very valuable to us. There are a couple of type constraints (ala type class constraints) that make most of this work. There's a constraint that looks like 'r={lbl:h * t}' that decides if/how a type "r" can be broken into a head field of type "h" (with a field named "lbl", this type variable gets the field name and can be used to e.g. relate one record type to another, like for deciding structural subtyping conversion), and a successor record type "t" (this bottoms out in the unit type). There's also a constraint "r.f::x" (or we write "r/f::x" if "f" is a type variable) which decides if/how the type "r" can be indexed by the field name "f" to determine a type "x". (Field access can also be overloaded, and we have some pretty awesome use-cases for that, hopefully I can put up some examples of that shortly.) So e.g. we can use the destructuring constraint to make a generic print function for all record types, like: instance (r={lbl:h*t}, Print h, Print t) => Print r where print x = do{putStr(lbl++":");println(recordHead(x));print(recordTail(x));} The field access constraint makes basic function definitions trivially "duck typed". So e.g. if I write ".jimmy" (shorthand for "\x.x.jimmy" or if you prefer Haskell syntax this would be like "\x -> x.jimmy") then it will select the "jimmy" field of whatever type it is given, however that is done for that particular type. There's a lot more to say on this point but maybe it should be turned into its own doc on the site...
- willtim 9y agoAh overloaded field access, that explains the type signature. I implemented a very similar extensible record/variant system for a product definition language at Barclays. I hope we see a lot more structural typing in industry going forward, it is an especially good fit for typing queries.