Thread: [q-lang-users] Query about Type Tests (Complex and Rational).
Brought to you by:
agraef
From: Rob H. <hub...@gm...> - 2006-06-15 12:33:21
|
The following are from Albert's complex.q revision 1.5, which is undergoing review at the moment, and my rational.q revision 160. public type Complex : Num; iscomplex _:Complex = true; iscomplex _ = false otherwise; public type Rational : Num; is_rational _:Rational = true; is_rational _ = false; is_rat_or_int _:Rational = true; is_rat_or_int _:Int = true; is_rat_or_int _ = false; I'm not sure the type guard "C:Complex" and function application "iscomplex C" should be related this closely; Similarly for "Q:Rational" and "is_rational Q". Perhaps these should be iscomplex _:Complex = true; iscomplex R = isreal R otherwise; //behavioural change isreal _:Real = true; isreal Q = isrational Q otherwise; // this won't work unless rational.q is included (or preluded) // thus might need to do e.g. "isint Q or else ..." isrational _:Rational = true; // slight rename isrational Z = isint Z otherwise; //behavioural change /* (scrap is_rat_or_int) */ isint _:Int = true; isint _ = false otherwise; (On the other hand, I think it would be wrong for Real to be a subtype of Complex.) I think I need clarification on (1) When one type should be a subtype of another. (2) What the semantics of type test function (such as iscomplex) is supposed to be. For example, for (1), suppose that there are the following types: Num | | C[R] denoting Complex [with Real parts] / \ / \ C[Q] R = Real / \ / / \ / C[Z] Q = Rational \ / \ / Z = Int (C[Z] is the ring of Gaussian Integers.) Should these types be related as supertype:subtype, and can Q express these (especially where there is more than one supertype)? Alternatively, should the only relationships be with Num as the common supertype? For (2), should e.g. "iscomplex" mean "is of Complex type or has a value that may be expressed (exactly?) as a Complex". (I'm ignoring, for the moment, the problem that a large Int can only be converted approximately to a Float. I'm assuming that Real and Float are equivalent.) I'd appreciate any feedback; it would help with my rational.q and an experimental "hypercomplex.q" that I'm (tentatively) working on. Thanks, Rob. |
From: John C. <co...@cc...> - 2006-06-15 14:32:47
|
Rob Hubbard scripsit: > I think I need clarification on > (1) When one type should be a subtype of another. > (2) What the semantics of type test function (such as iscomplex) is > supposed to be. Well, FWIW I'll tell you how Scheme does it. (For Schemers, I'm oversimplifying some and blurring some distinctions between R5RS and R6RS-draft.) In Scheme, the predicates "number?", "complex?", "real?", "rational?", and "integer?" refer to the mathematical concepts, not the representations. Thus on "normal" implementations, "number?" and "complex?" are the same thing, and "integer?" returns true for any integral value, even if the underlying representation is floating-point. "Real?" and "rational?" are not quite the same, because the former conventionally includes IEEE infinities whereas the latter does not. Cutting across this hierarchy or "tower", there are also the predicates "exact?" and "inexact?". On "normal" implementations, standard machine floating-point representations are inexact; machine integers ("fixnums"), arbitrary-precision integers ("bignums"), and pairs whose numerator and denominator are integers ("ratnums") are exact. Note that a complex number is only real if its imaginary part, expressed or implied, is an *exact* 0, because 0.0 actually represents every number between the smallest representable positive float and its negation. So 1 is exact and integer (and therefore also rational, real, and complex); 1.0 is inexact and integer (and rational and real and complex); 1.1 is inexact and rational (and real and complex); 11/10 is exact and rational (and real and complex); 1+2i is exact and complex; 1.0+0i is inexact and real (and complex); 1.0+0.0i is inexact and complex. Though not part of the standard, one can write some predicates that enquire about representations, assuming that the shortest representation is always used. It's impossible to write "fixnum?" in portable Scheme, because it depends on the size of machine integers. The others can be written for "normal" Scheme implementations as follows (not Scheme syntax): bignum? = integer? and exact? and not fixnum? ratnum? = rational? and exact? and not integer? compnum? = complex? and not real? Some Schemes use different representations for exact and inexact compnums, where the former is a pair of pointers and the latter is a pair of unboxed floats. I hope this is helpful in clarifying everyone's thinking. Feel free to ask questions about unclarities. -- And through this revolting graveyard of the universe the muffled, maddening beating of drums, and thin, monotonous whine of blasphemous flutes from inconceivable, unlighted chambers beyond Time; the detestable pounding and piping whereunto dance slowly, awkwardly, and absurdly the gigantic tenebrous ultimate gods -- the blind, voiceless, mindless gargoyles whose soul is Nyarlathotep. (Lovecraft) John Cowan|co...@cc...|ccil.org/~cowan |
From: Albert G. <Dr....@t-...> - 2006-06-15 21:24:42
|
Hi Rob, well, you caught me "in flagranti" before the new "numeric tower" (which is in fact more like an appartment building with 3 floors ;-) is actually finished (I still have to add Rational to the picture). I haven't discussed this on the list yet, because I first wanted to test out things for myself. Rob Hubbard wrote: > Num > | > | > C[R] denoting Complex [with Real parts] > / \ > / \ > C[Q] R = Real > / \ / > / \ / > C[Z] Q = Rational > \ / > \ / > Z = Int > > (C[Z] is the ring of Gaussian Integers.) > > Should these types be related as supertype:subtype, and can Q express > these (especially where there is more than one supertype)? Unfortunately not, since Q only has single inheritance. Another limitation is that you cannot make Rational a supertype of Int. The supertype is set when a type is declared and it cannot be changed after that; so Int, as a built-in type, can only be given another built-in type as a supertype. As John has pointed out, it's useful to distinguish between syntax and semantics here. Data types are a syntactic concept; they are all about representations of certain kinds of data, and which operations apply to what data. Then there's the semantic level, our interpretation of what these representations actually mean in an ideal mathematical world. Right now I'm just trying to get the data types right so that they will work in the intended way. So I've introduced the abtract data type Real purely out of practical considerations, since I want to be able to extend the built-in system of number types at all levels. In the new system alternative integer types can now be derived from Int, alternative floating point types from Float, other subtypes of real numbers (like Rational) from Real, and other types of non-real numbers (like Complex) from Num. So the new system looks like this (Rational already included in the picture, although this hasn't been implemented in the standard library yet): Num --> Real --> Int + +-> Float + +-> Rational +-> Complex This has the big advantage over the former system with just two levels (Num as a supertype versus the rest) that Complex (which is now a subtype of Num) can now be an aggregate of two Real's and will hence just work with any other user-defined data types derived from Real or any of its subtypes, too. The (syntactic) predicates associated with these types are isnum, isreal, isint, isfloat, isrational and iscomplex. If we also add the (semantic) predicates is_complex_rational, is_complex_int as well as is_real_or_complex and is_int_or_rational, then all remaining memberships in your diagram can be tested easily. I obviously just followed the KISS principle here, but so far it seems to work pretty well. The only real shortcoming I see is that Int is not a subtype of Rational and Real not a subtype of Complex. So, e.g., if you want to have a function which operates on both Int's and Rational's you cannot just define it on Rational arguments and be done with it. OTOH, Rational and Int are sufficiently different so that this can actually be justified, and if you really have an operation which can be defined in a generic fashion on both Int's and Rational's then chances are good that it can actually be defined on Real anyway. The same applies to Real and Complex and their common supertype Num. If you hold on for a little longer then I can complete the new implementation by integrating Rational into the standard library (maybe tonight). I could then release a candidate so that everybody can actually try it out and we can go on discussing it. Ok? Cheers, Albert -- Dr. Albert Gr"af Dept. of Music-Informatics, University of Mainz, Germany Email: Dr....@t-..., ag...@mu... WWW: http://www.musikinformatik.uni-mainz.de/ag |
From: Albert G. <Dr....@t-...> - 2006-06-15 21:30:28
|
Rob Hubbard wrote: > Perhaps these should be > > iscomplex _:Complex = true; > iscomplex R = isreal R otherwise; //behavioural change I don't think that this is a good idea. The other type checking predicates isxyz for a type Xyz all follow the scheme that the predicate is equivalent to the type guard, so iscomplex should follow that principle, too (that wasn't the case previously, but previously there was no Complex type and iscomplex was a semantic predicate). -- Dr. Albert Gr"af Dept. of Music-Informatics, University of Mainz, Germany Email: Dr....@t-..., ag...@mu... WWW: http://www.musikinformatik.uni-mainz.de/ag |
From: John C. <co...@cc...> - 2006-06-15 21:45:35
|
Albert Graef scripsit: > I don't think that this is a good idea. The other type checking > predicates isxyz for a type Xyz all follow the scheme that the predicate > is equivalent to the type guard, so iscomplex should follow that > principle, too (that wasn't the case previously, but previously there > was no Complex type and iscomplex was a semantic predicate). I'm not sure I see the utility of this. Granted that non-numeric types work this way, why should the numeric ones? I'd favor a scheme in which you use the guards for syntactic types and the isX predicates for semantic types. What can you do with iscomplex that you can't do with a type guard? Or if you think this is essential, how about going to a scheme in which isX means "is it the representation type" and "is_X_number" means "does it actually fit the model for that kind of number"? So iscomplex would be true only of objects of type Complex, but is_complex_number would be true of any number (except hypothetical quaternions and octonions to be added later). In particular, is_integral_number would be true of Floats with integer values. A less verbose naming scheme would be good, though. -- John Cowan http://ccil.org/~cowan co...@cc... [T]here is a Darwinian explanation for the refusal to accept Darwin. Given the very pessimistic conclusions about moral purpose to which his theory drives us, and given the importance of a sense of moral purpose in helping us cope with life, a refusal to believe Darwin's theory may have important survival value. --Ian Johnston |
From: Rob H. <hub...@gm...> - 2006-06-15 22:05:44
|
John Cowan wrote: > Albert Graef scripsit: > >> I don't think that this is a good idea. The other type checking >> predicates isxyz for a type Xyz all follow the scheme that the predicate >> is equivalent to the type guard, so iscomplex should follow that >> principle, too (that wasn't the case previously, but previously there >> was no Complex type and iscomplex was a semantic predicate). >> I'd be happy with that. I was trying to get a handle on what the convention was. > I'm not sure I see the utility of this. Granted that non-numeric > types work this way, why should the numeric ones? I'd favor a scheme > in which you use the guards for syntactic types and the isX predicates > for semantic types. What can you do with iscomplex that you can't do > with a type guard? > > This? func X = func1 Temp if iscomplex Temp where Temp = func2 X; > Or if you think this is essential, how about going to a scheme in which > isX means "is it the representation type" and "is_X_number" means "does > it actually fit the model for that kind of number"? So iscomplex would > be true only of objects of type Complex, but is_complex_number would be > true of any number (except hypothetical quaternions and octonions to be > added later). > If you decide to go down this route, then what about "isComplexType" versus "isComplexValue"? (But shorter.) Or e.g. "isComplex" versus "inComplex". (Perhaps these are too similar.) |
From: John C. <co...@cc...> - 2006-06-16 04:58:28
|
Albert Graef scripsit: > You can only use a type guard on the lhs of equations and variable > definitions, whereas the predicates can be used everywhere on the rhs > and on temporary computed values, too. So, yes, they are both useful. Oops, yes, of course. > Like isintnum, iscomplexnum, etc. Maybe we should also add isexact? Sounds good. And isinexact (which would be true of floats and of complex numbers with at least one float component). -- In politics, obedience and support John Cowan <co...@cc...> are the same thing. --Hannah Arendt http://www.ccil.org/~cowan |
From: John C. <co...@cc...> - 2006-06-16 21:25:14
|
Albert Graef scripsit: > John Cowan wrote: > >>Like isintnum, iscomplexnum, etc. Maybe we should also add isexact? > > > > Sounds good. And isinexact (which would be true of floats and of > > complex numbers with at least one float component). > > Wouldn't 'isinexact' simply be the negation of 'isexact'? I would assume these predicates return false on non-numbers. (In fact, the Scheme equivalents throw errors on non-numbers, which I consider a defect.) -- John Cowan co...@cc... http://ccil.org/~cowan In the sciences, we are now uniquely privileged to sit side by side with the giants on whose shoulders we stand. --Gerald Holton |
From: Albert G. <Dr....@t-...> - 2006-06-16 21:56:27
|
John Cowan wrote: > I would assume these predicates return false on non-numbers. Hmm, I wouldn't. The concept of 'exactness' applies to numbers, so I would let isexact fail on objects which are not of type Num. But of course in Q it's easy for the programmer to then just add an equation 'isexact _ = false otherwise' to his application if he thinks that this is more appropriate. -- Dr. Albert Gr"af Dept. of Music-Informatics, University of Mainz, Germany Email: Dr....@t-..., ag...@mu... WWW: http://www.musikinformatik.uni-mainz.de/ag |
From: Albert G. <Dr....@t-...> - 2006-06-15 22:00:54
|
John Cowan wrote: > I'm not sure I see the utility of this. Granted that non-numeric > types work this way, why should the numeric ones? I'd favor a scheme > in which you use the guards for syntactic types and the isX predicates > for semantic types. What can you do with iscomplex that you can't do > with a type guard? You can only use a type guard on the lhs of equations and variable definitions, whereas the predicates can be used everywhere on the rhs and on temporary computed values, too. So, yes, they are both useful. > Or if you think this is essential, how about going to a scheme in which > isX means "is it the representation type" and "is_X_number" means "does > it actually fit the model for that kind of number"? So iscomplex would > be true only of objects of type Complex, but is_complex_number would be > true of any number (except hypothetical quaternions and octonions to be > added later). That's a good idea! I can work out something along this line, but suggestions and code are welcome. > In particular, is_integral_number would be true of Floats with integer > values. A less verbose naming scheme would be good, though. Like isintnum, iscomplexnum, etc. Maybe we should also add isexact? Albert -- Dr. Albert Gr"af Dept. of Music-Informatics, University of Mainz, Germany Email: Dr....@t-..., ag...@mu... WWW: http://www.musikinformatik.uni-mainz.de/ag |
From: Albert G. <Dr....@t-...> - 2006-06-16 21:06:57
|
John Cowan wrote: >>Like isintnum, iscomplexnum, etc. Maybe we should also add isexact? > > Sounds good. And isinexact (which would be true of floats and of > complex numbers with at least one float component). Wouldn't 'isinexact' simply be the negation of 'isexact'? -- Dr. Albert Gr"af Dept. of Music-Informatics, University of Mainz, Germany Email: Dr....@t-..., ag...@mu... WWW: http://www.musikinformatik.uni-mainz.de/ag |