3 ms·
There's a fundamental opposition between the functional programming approach to types and array programming principles, as I see it. In functional programming (
by mlochbaum 3y ago
There's a fundamental opposition between the functional programming approach to types and array programming principles, as I see it. In functional programming (particularly Haskell), types are used to make fine distinctions for safety. Even if an existing type would work for something, it's often recommended to make a new one so two different use cases don't get mixed up. But the APL family works to make as few type distinctions as possible: everything is an array, booleans are numbers, and some k features are to unify multi-dimensional arrays with nested ones and sort-of-unify (it's complicated) functions, dicts, and arrays.
The reason to do this is that it allows one function to do more things. As you guessed, the matmul function from the tutorial works if the right argument has rank 1 or more, which means it also does matrix-vector products. Less code is another form of safety, the theory goes. And handling more things with the same function also lets you draw higher-level connections.
Of course you can type the arrays anyway. Remora is one attempt. To me it feels like just a technical exercise and I think this question calls for more high-level investigation of what exactly the goals are before jumping into PL theory details.
EDIT: Tali Beynon's rainbow arrays don't have all the answers, but I think they're a good example of the sort of investigation I mean: https://math.tali.link/classical-array-algebra/ https://math.tali.link/classical-array-algebra/
- dan-robertson 3y agoI want a type system that can reject attempts to add a vector of length 3 to a matrix of size 4x5. And I would want it to allow writing a single type for + rather than the way that Julia (iirc) handles these cases where there are various methods and the rules of method selection are applied to construct the effective method that does the right broadcasting.
- Twey 3y agoThis isn't really a fundamental disagreement. If we think of array functions as functions `Array<Index1, Element1> → Array<Index2, Element2>`, then essentially all you need to be able to say is that a function is generic over `Index1` and calculates some output index type `Index2` as a function of `Index1`. This is perfectly possible to do with Rust traits or Haskell type classes (although not all that ergonomic).