Hacker News new | past | comments | ask | show | jobs | submit login
What is a primitive? (mlochbaum.github.io)
30 points by chrispsn on Aug 5, 2021 | hide | past | favorite | 18 comments



Author here if you have any questions. The main reason to write this document is people used to APL wondering why BQN leaves out certain primitives (answer: I don't think they're really primitives), but probably more HNers would wonder why it has so many that ASCII isn't even fit to keep them all (the full list is at https://mlochbaum.github.io/BQN/doc/primitive.html). Just as well; hopefully I've addressed both concerns!


I think that you're after the universal morphisms in a computational category. Curien called them "categorical combinators" and gave a listing in https://core.ac.uk/download/pdf/82017242.pdf


I doubt it? Universal constructions give a nice definition for a few operations but I doubt they have the power to pull out all primitives, that is, select out of all the well-defined things you could do the ones that are natural or useful. Can Indices[0] be constructed as a universal morphism? Is defining it in this way simpler than an algorithmic definition, which can be quite short? One of the properties of primitives I list is that they tend to have short definitions, so constructive definition is already a sort of filter that prefers primitives. Universal morphisms might be another, even a more useful, filter, but probably not a perfect filter.

Although, if you're here... there's a more focused question that's been bothering me because I feel it should appear in category theory but can't locate it. There's an operation I call Under that I partially introduce at [1] and define at [2]. The idea is that given functions F and G, where G manipulates things in some overall framework like arrays, F⌾G is a function so that F⌾G x is as similar as possible to x while satisfying (G F⌾G x) = G x. Maybe it's a sort of pullback along a functor G. Does that look familiar?

[0] https://mlochbaum.github.io/BQN/doc/replicate.html

[1] https://mlochbaum.github.io/BQN/tutorial/variable.html#modif...

[2] https://mlochbaum.github.io/BQN/spec/inferred.html#under


While I haven’t (yet?) taken the time to understand the notation you are using to define this “under” operation, it sounds a little like an adjoint of a functor?

But I could very well be totally off.


The structure is pretty similar. If you could encode array structures into categories (part of my problem is I don't know how to do this effectively: are the structures objects, or categories?), then my take is that a structural function that extracts some part of an array should give a functor G. Then a right adjoint ⌾G puts the omitted structure back. But I don't think this can work, because the definition of an adjoint says morphisms in the target of G exactly correspond to morphisms in its source, when ⌾G is used to find the codomain. This doesn't match up: if G extracts structure, then it should collapse some functions together, when they only differ in what they do to the parts of the array that get left out.

Most of my problem seems to be that the definition of Under really depends on applying functions to particular arguments. So it's hard to see how to set up categories to capture the necessary properties. But I don't know if it's actually hard to do or just confusing.


What tool did you use to make those diagrams?


BQN! The entire BQN website is generated with a markdown processor[0] that handles the parts of Github-flavored markdown I use and adds features like highlighting and the ability to drop into BQN to generate html or svg. Github doesn't display markdown source nicely, but you can scroll down to the <!--GEN line in [1] to see how this diagram is made (plus definitions at [2]).

[0] https://github.com/mlochbaum/BQN/blob/master/md.bqn

[1] https://raw.githubusercontent.com/mlochbaum/BQN/master/comme...

[2] https://github.com/mlochbaum/BQN/blob/master/svg.bqn



The relationship is interesting. Chris is trying to find a minimal set of functions good enough to derive the rest (a worthwhile goal, and it mentions at the bottom that I did something similar in BQN). Part of my current thinking about primitives is that it's not important how many there are, more that each represents a coherent simple concept. But primitives that are too similar can cause problems for memory and maybe intuition.


What is your opinion of the j. primitive in j?


It makes complete sense and I'll add the same thing to BQN if it gets complex numbers (this is why ⍳ is on the keyboard, but other options could be better).


When I write programming languages, I usually define primitives as "any value without children". Strings, numbers, booleans, are primitives. Collections and records are not.

Some edge cases: literal ranges would be primitives, because their ast is represented (in Haskell) as "Range Int Int". Ranges which take values wouldn't be primitives, because their ast is represented as "Range expr expr"


BQN uses the term "atom" for such values[0]. They include numbers, characters, and functions, as well as namespaces—really "atom" just means "non-array". These are the values that can't be split apart by array operations, but they might still be made up of multiple things, for example a function train[1].

In contrast, primitives are the starting point for programming, particularly tacit programming ("point-free" in Haskell). While the two names have a similar meaning, I think it fits a little better to call values that are indivisible from a particular perspective "atoms" and the ones that are meant to really be fundamental "primitives".

[0] https://mlochbaum.github.io/BQN/doc/types.html

[1] https://mlochbaum.github.io/BQN/doc/train.html


Are you saying that you consider strings in Haskell to be a primitive?


No, Haskell is weird since a string is [Char]. If it was it’s own value, yes.

The languages i’ve written are pretty basic. e.g. the data types might be

- Number - String - True, false, null - Array of values - Record of fields (key + value) - Variant of options (key + value)

So the distinction is clearer.


> No, Haskell is weird since a string is [Char].

I can think of various langages where string is not a built-in, but i can’t think of a langage where string is not some sort of sequence, not just in its implementation but in its interface.

The definition also breaks down quickly e.g. is a complex a primitive? If not because they have real and imaginary parts, why are floats which have a mantissa and an exponent? And what about functions? What even is a child? Are value-less sum types primitives but valued ones not?

More importantly, how does it matter? What does the distinction you draw provide that is useful?


Is BQN a near-incrementing of the letters in APL?

Is it pronounced "bacon"?


Yes, as you can verify pretty easily in BQN: https://mlochbaum.github.io/BQN/try.html#code=IkJRTiItIkFQTC.... I explained at https://news.ycombinator.com/item?id=24172488.

Like APL versus "apple", the normal pronunciation is to spell it out B-Q-N, but it may be pronounced "bacon" if one wishes to establish a double-entendre. So a BQN user is a BQNator, pronounced like https://en.wikipedia.org/wiki/Baconator.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: