Methods that accept an integer will also accept Z{P}, so you may gain access to that functionality. This depends on that you have correctly implemented the basic functionality (or ‘interface’) of Integer, otherwise it may end throwing errors or doing strange things. My code examples probably has not done that.
You cannot use that functionality for Z{P}, or you’ll have to implement it yourself. Off the top of my head I can’t remember what functionality that would be, but basically any method that someone has written with ::Integer in its type signature.
Then the pool of available methods that work ‘out of the box’ for your method is a bit smaller.
That won’t work. You cannot subtype a concrete type, only abstract types.
It’s a bit unfortunate that the interfaces to base types (Integer, Number, etc) aren’t documented better. In lieu of that the documentation of the array interface is a decent conceptual substitute. If you have a type that you want to behave like an array you can subtype abstractarray, and implement the few functions listed in the documentation and your new type will get all the functions already defined for abstractarrays across the ecosystem.
The same is true of Integer, Number, etc. but the required functions are not as well documented.
Indeed. While I was typing up that Z{P, T} code, I was constantly running into weird effects, such as
>> length(Z13(0):Z13(12))
0
and collect returned an empty vector, even though I could iterate over it and print all the elements.
It felt a bit like playing whack-a-mole. New problems kept popping up when I tried new things, then I tried, half-blindly, to patch up the necessary functionality, but ended up creating ambiguity problems because I didn’t know which methods to add, and some of the time I chose the wrong ones.
A bit frustrating, and I have no idea if I’m even close, what to add, what to remove, and when the next error will pop up.
I understand that Julia’s abstract types are the equivalent of C++ abstract classes or Java interfaces. Don’t know anything equivalent in Python’s world.
The best bet would probably be to find a package that implements a new type subtyping the same abstract type you wish to subtype and see what they implement. For example if you wanted to create a new <: Real, looking at the Rational type in base would be good as presumably it implements all needed functions. There are surely packages out there that subtype integer already to crib off of.
Wow. I just realized that basing the Z{P, T} type on UInt was a bad idea! Wraparound effects when subtracting are plain wrong. Use Int (or Int8 etc. instead!!)
Have you tried looking at how an existing package defines new number types?
For example, GaloisFields.jl implements finite fields. This package implements a lot of features, but the basic number type for prime fields is implemented here.
Another nice and relatively simple example of a custom number type can be found in the Quaternions.jl package, which defines a quaternion type here.
Good evening ! (night is coming in my native France).
Let’s continue, if you agree with my continuing questions. I will play the ‘Candide’ role or ‘advocate of the devil’ according the situation. It’s just a matter of style to stimulate the debate.
OK as I understood you derive (sub-type) from some abstract type to access functionality.
But in any case you’re obliged to explain Julia how to add, multiply, subtract F_p objects, just like me who didn’t use any sub-typing.
We do the same things parallel, don’ t we ?
You :
`Base.:+(a::Z{P}, b::Z{P}) where {P} = Z{P}(a.x + b.x)
Base.:-(a::Z{P}, b::Z{P}) where {P} = Z{P}(a.x - b.x)
Base.:-(a::Z{P}) where {P} = Z{P}(-a.x)
Base.:*(a::Z{P}, b::Z{P}) where {P} = Z{P}(a.x * b.x)type or paste code here
me :
For sure I’ll have a look at this.
For now I have no ambitions except teaching the base of linear algebra using simple programs as examples (python and now julia //)
But I just published a site of algebra specially dedicated to mobile devices (telephones and tablets). Sorry but everything is in French.
For the moment the algebra site has a development mainly guided by historical considerations. As a consequence complete results concern mostly the characteristic 0 where separability is obvious.
Nevertheless it’s my intention to develop more the general theory and to give examples with appropriate programs.
So I will need models for Fp polynomials, Fp-vector spaces, finite extension of Fp and so on to make computations.
For sure this module will be of great help.
This is a plan for future now I’m busy with learning correct use of sub-typing, parametric types and so on.
There are functions which are defined for Integer directly and therefore also for all its suptypes.
For example, when you take @DNF s simpler example without the subtyping, you couldn’t do
Yes, you have to define a limited number of methods, like basic arithmetic. But every other method that anyone ever defines for Integer, which could be any countless number, are now available, as well as all the functionality that derives from those again.
I think this is the source of a lot of your confusion here. Julia has nothing at all equivalent to C++'s abstract classes. Python classes are similar to C++'s (except python people would typically add in an old school raise NotImplemented for any methods not defined rather than actually having it abstract. See class - Is it possible to make abstract classes in Python? - Stack Overflow Java Interfaces are a little bit closer, but even then I don’t think it is the right way to think about it.
The closest thing in C++ are trait classes. Remember that Julia is much closer to the parametric/generic programming in C++ than anything object orietned. Look at code which uses overloading of functions defined on templated classes in C++ to get into the right spirit. With C++ overloading and templates, you can have things “dispatch” statically to different functions, but it is tough to carefully control which functions are called.
So when doing generic programming in C++ you sometimes subclass from a empty classes (these are not abstract in the sense of having a non-implemented member function). These are just used to organization of traits for dispatching. But don’t be fooled as the use of a class and inheritance from them is just a trick, and has nothing to do with classes in object-oriented programming. This has some of the tricks in this insanity: http://cppedinburgh.uk/slides/201603-tmp.pdf Also Substitution failure is not an error - Wikipedia explains some of this stuff
With that C++ lets you rig up what you could call “multiple static dispatch” for functions when all of the types are known at compiletime - although it is often incredibly painful to get there.
OK, now forget all of that if you didn’t know it. C++ is powerful but insane due to people having to find hacks to implement these features on an old language. In Julia you can do dynamic dispatch at runtime and with different specializations for all of the parameters of the function (i.e. multiple dispatch). The abstract types are your way to use existing code for the implementations of your functions if they fit into the same “interface” in a loose generic programming sense.
Yes, I tried with Integer sub-typing a^n is evaluated correctly for n integer >0 without any extra-code except overloading of *.
But a^0 and a^-1 lead (logically) to errors.
Can you find one or two examples let’s say more ‘spectacular’ because honestly I’m not too much impressed by this one. In a field you must be able to compute any power positive or negative of any non null element. To do this you have to overload iszero and inv and define a ^k so to redefine on the way the positive powers isn’t much job.
Examples given by DNF are more convincing But it is the explicit ‘promotion rule’ which does the job.
Well, access to some functionality is not straightforward from derivation.
OK forget about this, I mean benefit of sub-typing now. As I answered to Fliks it seems to me modest without the associated promotion rule.
I made some test with my simple and naive definition of Z_p with a global p (which you hate). I adapted
your rule to my context
and after this I could multiply a F_p by a natural
So to this point Julia knows how to multiply two F_p, how to multiply two naturals and by promotion a natural by a F_p 12a and a*12 are understood and give the same result.
I tried to make some changes . Actually your rule converts any Type sub-typing the very general Number abstract type to F_p. But in reality it is just necessary to convert integers. So I changed :<Number for :<Integer it works. What is the reason of your choice (I mean Number and not Integer) ?
As I understood it is only possible from a type to a sub-type, not conversely. One cannot decide to identify a F_p with it’s x member, or is it possible and how to do it.
This is pure curiosity I don’t see any practical interest to do it now, I just want to close the chapter of explicit promotion-conversion rules.
You mean in this particular case? I don’t have an overview of that, it depends on what you want to do. If you have no interest in functionality beyond basic arithmetic, then you don’t need subtyping. I found that printing of arrays is nicer when you subtype Integer, but that’s just my preference.
Sure. But why not use both?
I’m sure it works, I just don’t think students should learn to use globals like that. And it’s less elegant, and less readable and instructive. Type parameters seem to map so cleanly to the parameterization of Zp, it seems like a good case for demonstrating both.
The reason is arbitrary and not properly thought-out. I wanted 2.0 * z and so on to work.