Don't hardcode that certain types are leaves in functor implementation
Motivation and description
It doesn't seem right to hardcode that e.g. AbstractArray{<:Number} is a leaf via making the functor for this type never recurse into its children. This makes it harder when the user wants to, e.g. apply a function to every scalar leaf without worrying about arrays.
Possible Implementation
The exclude function already has the ability to stop higher up in the tree. So perhaps all leaf information should be encoded in the exclude function: if we want to stop at a node, simply don't call functor on it in the first place. Then, maybe:
functorshould search for children as aggressively as possible, not stopping e.g. atAbstractArray{<:Number}- doing
@leaf AbstractArray{<:Number}would directly affect the defaultisleaffunctionality, which is used inexclude, so the previous behaviour would apply by default.
Breaking changes aside, I don't see any major issues with this. Functors.jl is in a weird place because it was designed to be used as part of Flux's module system, yet was written as if it were a generic struct traversal library. The upside is that more libraries outside of FluxML have been able to adopt it, but the downside is confusion from some parts seeming too task-specific (e.g. saying all numeric arrays are leaves) and others seeming too general (how many people know what fmap means?).
Maybe we should allow users to pass their own functor-like function to fmap.
We can also provide a set of functor variations like the aggressive functor proposed here.
One option is to build the default functor on ConstructionBase (which will recurse arrays). Then adopt #41 with a Numeric tag that applies to numbers and numeric arrays.
https://github.com/chengchingwen/StructWalk.jl allows to define customized walks
I would close this as not planned, since people can just handle numerical arrays or use StructWalk.jl instead.