Null is not just an undefined thing. It explicitly indicates that processing has been attempted. It is the result of something, but the result could not be computed or represented as expected. The conceptual difference between null and undefined is fairly well illustrated at https://fullstackgeek.blogspot.com/2019/01/functions-in-javascript.html.
https://en.wikipedia.org/wiki/Nullable_type: "NULL is frequently used to represent a missing value or invalid value, such as from a function that failed to return or a missing field in a database, as in NULL in SQL."
https://docs.raku.org/type/Nil: "The value Nil may be used to fill a spot where a value would normally go, and in so doing, explicitly indicate that no value is present. It may also be used as a cheaper and less explosive alternative to a Failure. (In fact, class Failure is derived from Nil, so smartmatching Nil will also match Failure.)"
The above two conceptual descriptions feel extremely similar, at least to me.
Undefined literally means that something has not been defined/assigned to, or has no value whatsoever. Whatever Raku's "no declared type and no assigned value" circumstance defaults to, seems like it really ought to map to CBOR undefined (again, well-illustrated in the JavaScript explanation above). I defer to Raku/Rakudo to make the bulk of this argument for me:
raku -e '($).raku.say' # if I declare no type and assign no value, what is the spec'd result?
Any
raku -e undef # We literally had "undef" in P5, so what does Rakudo suggest the Raku equivalent is?
===SORRY!=== Error while compiling -e
Unsupported use of undef as a value. In Raku please use: something
more specific: an undefined type object such as Any or Int, :!defined as
a matcher, Any:U as a type constraint, Nil as the absence of an expected
value or fail() as a failure return .
at -e:1
------> undef⏏<EOL>
It'd seem rather odd to pass Any in and get Mu out, especially since you'll see Any whenever the flow of execution didn't assign a value (whether by bug or design). Any is far more commonly seen than Mu, in my experience.
Yes, arrays and hashes default to allowing Mu. However, even they default to Any when reading from unassigned indices. The Mu in these cases is because it is being used as a type constraint, and we want to allow Junctions to be stored in them by default. When representing data as CBOR, you aren't typically talking about type constraints and class heirarchies, you're talking about values themselves. That's kind of implicit in the whole concept of "data," IMO. While metaprogramming might lead you to pass schemas around as data contrary to the previous two sentences, I'd say that's definitely the exception rather than the rule, and probably not something most people would be immediately inclined to use CBOR for. The only other counterpoint I can think of is "But Junctions are Mu, not Any, and I might want to support them," but if you do support Junctions, it certainly won't be as CBOR undefined, so supporting them or not is also irrelevant.
If you're just really attached to Mu, you could certainly still support the exceptional case of storing Mu itself in CBOR if you so chose, I just don't agree that undefined is the most correct way to implement it.