Re: Show, Eq not necessary for Num [Was: Revamping the numeric classes]

2001-02-11 Thread Marcin 'Qrczak' Kowalczyk

Sun, 11 Feb 2001 13:37:28 +1300, Brian Boutel [EMAIL PROTECTED] pisze:

 Can you demonstrate a revised hierarchy without Eq? What would
 happen to Ord and the numeric classes with default class method
 definitions that use (==) either explicitly or in pattern matching
 against numeric literals?

OK, then you can't write these default method definitions.

I'm against removing Eq from the numeric hierarchy, against making Num
instances for functions, but I would probably remove Show. I haven't
seen a sensible proposal of a replacement of the whole hierarchy.

 In an instance declaration, if a method requires operations of
 another class which is not a superclass of the class being instanced,
 it is sufficient to place the requirement in the context,

Better: it is sufficient if the right instance is defined somewhere.

-- 
 __("  Marcin Kowalczyk * [EMAIL PROTECTED] http://qrczak.ids.net.pl/
 \__/
  ^^  SYGNATURA ZASTPCZA
QRCZAK


___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe



Re: Show, Eq not necessary for Num [Was: Revamping the numeric classes]

2001-02-11 Thread William Lee Irwin III

Sun, 11 Feb 2001 13:37:28 +1300, Brian Boutel [EMAIL PROTECTED] pisze:
 Can you demonstrate a revised hierarchy without Eq? What would
 happen to Ord and the numeric classes with default class method
 definitions that use (==) either explicitly or in pattern matching
 against numeric literals?

I anticipate that some restructuring of the numeric classes must be
done in order to accomplish this. I am, of course, attempting to
contrive such a beast for my own personal use.

On Sun, Feb 11, 2001 at 07:59:38AM +, Marcin 'Qrczak' Kowalczyk wrote:
 OK, then you can't write these default method definitions.
 I'm against removing Eq from the numeric hierarchy, against making Num
 instances for functions, but I would probably remove Show. I haven't
 seen a sensible proposal of a replacement of the whole hierarchy.

Well, there are a couple of problems with someone like myself trying
to make such a proposal. First, I'm a bit too marginalized and/or
committed to a radical alternative. Second, I don't have the right
associations or perhaps other resources.

Removing Eq sounds like a good idea to me, in all honesty, though I
think numeric instances for functions (at least by default) aren't
great ideas. More details follow:

Regarding Eq, there are other types besides functions which might
not be good ideas to define equality on, either because they're not
efficiently implementable or are still inappropriate. Matrix types
aren't good candidates for defining equality, for one. Another one
you might not want to define equality on are formal power series
represented by infinite lists, since equality tests will never
terminate. A third counterexample comes, of course, from graphics,
where one might want to conveniently scale and translate solids.
Testing meshes and surface representations for equality is once
again not a great idea. Perhaps these counterexamples are a little
contrived, but perhaps other people can come up with better ones.

As far as the function instances of numeric types, there are some
nasty properties that they have that probably make it a bad idea.
In particular, I discovered that numeric literals' fromInteger
property creates the possibility that something which is supposed
to be a scalar or some other numeric result might accidentally be
applied. For instance, given an expression with an intermediate
numeric result like:

f u v . g x y $ h z

which is expected to produce a number, one could accidentally apply
a numeric literal or something bound to one to some arguments, creating
a bug. So this is for at least partial agreement, though I think it
should be available in controlled circumstances. Local module
importations and/or scoped instances might help here, or perhaps
separating out code that relies upon them into a module where the
instance is in scope, as it probably needs control which is that tight.

Sun, 11 Feb 2001 13:37:28 +1300, Brian Boutel [EMAIL PROTECTED] pisze:
 In an instance declaration, if a method requires operations of
 another class which is not a superclass of the class being instanced,
 it is sufficient to place the requirement in the context,

On Sun, Feb 11, 2001 at 07:59:38AM +, Marcin 'Qrczak' Kowalczyk wrote:
 Better: it is sufficient if the right instance is defined somewhere.

Again, I'd be careful with this idea. It's poor design to unnecessarily
restrict the generality of code. Of course, it's poor design to not try
to enforce necessary conditions in the type system, too, which is why
library design is nontrivial. And, of course, keeping it simple enough
for use by the general populace (or whatever semblance thereof exists
within the Haskell community) might well conflict with the desires of
persons like myself who could easily fall prey to the accusation that
they're trying to turn Haskell into a computer algebra system, and adds
yet another constraint to the library design making it even tougher.


Cheers,
Bill

___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe



Re: Show, Eq not necessary for Num [Was: Revamping the numeric classes]

2001-02-11 Thread Brian Boutel

Marcin 'Qrczak' Kowalczyk wrote:


 I'm against removing Eq from the numeric hierarchy, against making Num
 instances for functions, but I would probably remove Show. I haven't
 seen a sensible proposal of a replacement of the whole hierarchy.
 

Then we probably are in agreement. 

--brian

___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe



Re: Show, Eq not necessary for Num [Was: Revamping the numeric classes]

2001-02-11 Thread William Lee Irwin III

On 11-Feb-2001, Brian Boutel [EMAIL PROTECTED] wrote:
 There may be some misunderstanding here. If you are talking about type
 for which equality is always undefined, then I agree with you, but that
 is not what I was talking about. I was thinking about types where
 equality is defined for some pairs of argument values and undefined for
 others - I think the original example was some kind of arbitrary
 precision reals.

On Sun, Feb 11, 2001 at 06:24:33PM +1100, Fergus Henderson wrote:
 The original example was treating functions as a numeric type.  In the
 case of functions, computing equality is almost always infeasible.
 But you can easily define addition etc. pointwise:
   
   f + g = (\ x - f x + g x)

I have a fairly complete implementation of this with dummy instances of
Eq and Show for those who want to see the consequences of this. I found,
interestingly enough, that any type constructor f with the following
three properties could have an instance of Num defined upon f a:

(1) it has a unary constructor to lift scalars 
(2) it has a Functor instance
(3) it has an analogue of zip which can be defined upon it

or, more precisely:

\begin{code}
instance (Eq (f a), Show (f a), Num a, Functor f,
Zippable f, HasUnaryCon f) = Num (f a)
where
f + g = fmap (uncurry (+)) $ fzip f g
f * g = fmap (uncurry (*)) $ fzip f g
f - g = fmap (uncurry (-)) $ fzip f g
negate = fmap negate
abs = fmap abs
signum = fmap signum
fromInteger = unaryCon . fromInteger

class Zippable f where
fzip :: f a - f b - f (a,b)

class HasUnaryCon f where
unaryCon :: a - f a

instance Functor ((-) a) where
fmap = (.)

instance Zippable ((-) a) where
fzip f g = \x - (f x, g x)

instance HasUnaryCon ((-) a) where
unaryCon = const
\end{code}

and this generalizes nicely to other data types:

\begin{code}
instance Zippable Maybe where
fzip (Just x) (Just y) = Just (x,y)
fzip _ Nothing = Nothing
fzip Nothing _ = Nothing

instance HasUnaryCon Maybe where
unaryCon = Just

instance Zippable [ ] where
fzip = zip

instance HasUnaryCon [ ] where
unaryCon = cycle . (:[])
\end{code}

On 11-Feb-2001, Brian Boutel [EMAIL PROTECTED] wrote:
 Returning to the basic issue, I understood the desire to remove Eq as a
 superclass of Num was so that people were not required to implement
 equality if they did not need it, not that there were significant
 numbers of useful numeric types for which equality was not meaningful. 

On Sun, Feb 11, 2001 at 06:24:33PM +1100, Fergus Henderson wrote:
 The argument is the latter, with functions as the canonical example.

Well, usually equality as a mathematical concept is meaningful, but
either not effectively or efficiently computable. Given an enumerable
and bounded domain, equality may be defined (perhaps inefficiently)
on functions by

\begin{code}
instance (Enum a, Bounded a, Eq b) = Eq (a-b) where
f == g = all (uncurry (==))
$ zipWith (\x - (f x, g x)) [minBound..maxBound]
\end{code}

and as I've said in another post, equality instances on data structures
expected to be infinite, very large, or where the semantics of equality
are make it difficult to compute, or perhaps even cases where it's just
not useful are also not good to be forced.


Cheers,
Bill

___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe



Re: Revamping the numeric classes

2001-02-11 Thread Tom Pledger

Marcin 'Qrczak' Kowalczyk writes:
 | Fri, 9 Feb 2001 17:29:09 +1300, Tom Pledger [EMAIL PROTECTED] pisze:
 | 
 |  (x + y) + z
 |  
 |  we know from the explicit type signature (in your question that I was
 |  responding to) that x,y::Int and z::Double.  Type inference does not
 |  need to treat x or y up, because it can take the first (+) to be Int
 |  addition.  However, it must treat the result (x + y) up to the most
 |  specific supertype which can be added to a Double.
 | 
 | Approach it differently. z is Double, (x+y) is added to it, so
 | (x+y) must have type Double.

That's a restriction I'd like to avoid.  Instead: ...so the most
specific common supertype of Double and (x+y)'s type must support
addition.

 | This means that x and y must have type Double.  This is OK, because
 | they are Ints now, which can be converted to Double.
 | 
 | Why is your approach better than mine?

It used a definition of (+) which was a closer fit for the types of x
and y.

 :
 |  h:: (Subtype a b, Subtype Int b, Eq b) = (Int - a) - Bool
 | 
 | This type is ambiguous: the type variable b is needed in the
 | context but not present in the type itself, so it can never be
 | determined from the usage of h.

Yes, I rashly glossed over the importance of having well-defined most
specific common supertype (MSCS) and least specific common subtype
(LSCS) operators in a subtype lattice.  Here's a more respectable
version:

h :: Eq (MSCS a Int) = (Int - a) - Bool

 |  That can be inferred by following the structure of the term.
 |  Function terms do seem prone to an accumulation of deferred
 |  subtype constraints.
 | 
 | When function application generates a constraint, the language gets
 | ambiguous as hell. Applications are found everywhere through the
 | program! Very often the type of the argument or result of an
 | internal application does not appear in the type of the whole
 | function being defined, which makes it ambiguous.
 | 
 | Not to mention that there would be *LOTS* of these constraints.
 | Application is used everywhere. It's important to have its typing
 | rule simple and cheap. Generating a constraint for every
 | application is not an option.

These constraints tend to get discharged whenever the result of an
application is not another function.  The hellish ambiguities can be
substantially tamed by insisting on a properly constructed subtype
lattice.

Anyway, since neither of us is about to have a change of mind, and
nobody else is showing an interest in this branch of the discussion,
it appears that the most constructive thing for me to do is return to
try-to-keep-quiet-about-subtyping-until-I've-done-it-in-THIH mode.

Regards,
Tom

___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe



A sample revised prelude for numeric classes

2001-02-11 Thread Dylan Thurston

I've started writing up a more concrete proposal for what I'd like the
Prelude to look like in terms of numeric classes.  Please find it
attached below.  It's still a draft and rather incomplete, but please
let me know any comments, questions, or suggestions.

Best,
Dylan Thurston


Revisiting the Numeric Classes
--
The Prelude for Haskell 98 offers a well-considered set of numeric
classes which cover the standard numeric types (Integer, Int,
Rational, Float, Double, Complex) quite well.  But they offer limited
extensibility and have a few other flaws.  In this proposal we will
revisit these classes, addressing the following concerns:

(1) The current Prelude defines no semantics for the fundamental
operations.  For instance, presumably addition should be
associative (or come as close as feasible), but this is not
mentioned anywhere.

(2) There are some superfluous superclasses.  For instance, Eq and
Show are superclasses of Num.  Consider the data type

 data IntegerFunction a = IF (a - Integer)

One can reasonably define all the methods of Num for
IntegerFunction a (satisfying good semantics), but it is
impossible to define non-bottom instances of Eq and Show.

In general, superclass relationship should indicate some semantic
connection between the two classes.

(3) In a few cases, there is a mix of semantic operations and
representation-specific operations.  toInteger, toRational, and
the various operations in RealFloating (decodeFloat, ...) are the
main examples.

(4) In some cases, the hierarchy is not finely-grained enough:
operations that are often defined independently are lumped
together.  For instance, in a financial application one might want
a type "Dollar", or in a graphics application one might want a
type "Vector".  It is reasonable to add two Vectors or Dollars,
but not, in general, reasonable to multiply them.  But the
programmer is currently forced to define a method for (*) when she
defines a method for (+).

In specifying the semantics of type classes, I will state laws as
follows:
  (a + b) + c === a + (b + c)
The intended meaning is extensional equality: the rest of the program
should behave in the same way if one side is replaced with the
other.  Unfortunately, the laws are frequently violated by standard
instances; the law above, for instance, fails for Float:

  (1.0 + (-1.0)) + 1.0 = 1.0
  1.0 + ((-1.0) + 1.0) = 0.0

Thus these laws should be interpreted as guidelines rather than
absolute rules.  In particular, the compiler is not allowed to use
them.  Unless stated otherwise, default definitions should also be
taken as laws.

This version is fairly conservative.  I have retained the names for
classes with similar functions as far as possible, I have not made
some distinctions that could reasonably be made, and I have tried to
opt for simplicity over generality.  The main non-conservative change
is the Powerful class, which allows a unification of the Haskell 98
operators (^), (^^), and (**).  There are some problems with it, but I
left it in because it might be of interest.  It is very easy to change
back to the Haskell 98 situation.

I sometimes use Simon Peyton Jones' pattern guards in writing
functions.  This can (as always) be transformed into Haskell 98
syntax.

 module NumPrelude where
 import qualified Prelude as P
 -- Import some standard Prelude types verbatim verbandum
 import Prelude(Bool(..),Maybe(..),Eq(..),Either(..),Ordering(..),
Ord(..),Show(..),Read(..),id)

 infixr 8  ^
 infixl 7  *
 infixl 7 /, `quot`, `rem`, `div`, `mod`
 infixl 6  +, -

 class Additive a where
 (+), (-) :: a - a - a
 negate   :: a - a
 zero :: a

  -- Minimal definition: (+), zero, and (negate or (-1))
 negate a = zero - a
 a - b= a + (negate b)

Additive a encapsulates the notion of a commutative group, specified
by the following laws:

  a + b === b + a
   (a + b) + c) === a + (b + c)
   zero + a === a
 a + (negate a) === 0

Typical examples include integers, dollars, and vectors.

 class (Additive a) = Num a where
 (*) :: a - a - a
 one :: a
 fromInteger :: Integer - a

   -- Minimal definition: (*), one
 fromInteger 0 = zero
 fromInteger n | n  0 = negate (fromInteger (-n))
 fromInteger n | n  0 = reduceRepeat (+) one n

Num encapsulates the mathematical structure of a (not necessarily
commutative) ring, with the laws

  a * (b * c) === (a * b) * c
  one * a === a
  a * one === a
  a * (b + c) === a * b + a * c

Typical examples include integers, matrices, and quaternions.

"reduceRepeat op a n" is an auxiliary function that, for an
associative operation "op", computes the same value as

  reduceRepeat op a n = foldr1 op (repeat n a)

but applies "op" O(log n) times.  A sample 

Re: A sample revised prelude for numeric classes

2001-02-11 Thread Ashley Yakeley

At 2001-02-11 14:42, Dylan Thurston wrote:

I've started writing up a more concrete proposal for what I'd like the
Prelude to look like in terms of numeric classes.  Please find it
attached below.  It's still a draft and rather incomplete, but please
let me know any comments, questions, or suggestions.

Apologies if this has been discussed and I missed it. When it comes to 
writing a 'geek' prelude, what was wrong with the Basic Algebra Proposal 
found in ftp://ftp.botik.ru/pub/local/Mechveliani/basAlgPropos/ ? 
Perhaps it could benefit from multi-parameter classes?

-- 
Ashley Yakeley, Seattle WA


___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe



Re: A sample revised prelude for numeric classes

2001-02-11 Thread William Lee Irwin III

On Sun, Feb 11, 2001 at 05:42:15PM -0500, Dylan Thurston wrote:
 I've started writing up a more concrete proposal for what I'd like the
 Prelude to look like in terms of numeric classes.  Please find it
 attached below.  It's still a draft and rather incomplete, but please
 let me know any comments, questions, or suggestions.

This is great, it gets something concrete out there to comment on, which
is probably quite a bit of what needs to happen.

For brevity's sake, I'll have to chop up your message a bit.

 (1) The current Prelude defines no semantics for the fundamental
 operations.  For instance, presumably addition should be
 associative (or come as close as feasible), but this is not
 mentioned anywhere.

This is something serious, as I sort of took for granted the various
properties of operations etc. I'm glad you pointed it out.

 (2) There are some superfluous superclasses.  For instance, Eq and
 Show are superclasses of Num.  Consider the data type
 
  data IntegerFunction a = IF (a - Integer)
 
 One can reasonably define all the methods of Num for
 IntegerFunction a (satisfying good semantics), but it is
 impossible to define non-bottom instances of Eq and Show.
 
 In general, superclass relationship should indicate some semantic
 connection between the two classes.

It's possible to define non-bottom instances, for instance:

instance Eq (a-b) where
_ == _ = False

instance Show (a-b) where
show = const "function"

I suspect you're aware of this and had in mind the constraint that
they should also respect the invariants and laws of the classes.

  class (Additive a) = Num a where
  (*) :: a - a - a
  one   :: a
  fromInteger :: Integer - a

 Num encapsulates the mathematical structure of a (not necessarily
 commutative) ring, with the laws
 
   a * (b * c) === (a * b) * c
   one * a === a
   a * one === a
   a * (b + c) === a * b + a * c
 
 Typical examples include integers, matrices, and quaternions.

There is an additional property of zero being neglected here, namely
that it is an annihilator. That is,

zero * x === zero
x * zero === zero

Again, it's probably a reasonable compromise not to accommodate
nonassociative algebras, though an important application of them
lies within graphics, namely 3-vectors with the cross product.

 "reduceRepeat op a n" is an auxiliary function that, for an
 associative operation "op", computes the same value as
 
   reduceRepeat op a n = foldr1 op (repeat n a)
 
 but applies "op" O(log n) times.  A sample implementation is below.

This is a terrific idea, and I'm glad someone has at last proposed
using it.

  class (Num a) = Integral a where
  div, mod :: a - a - a
  divMod :: a - a - (a,a)
  gcd, lcm :: a - a - a
  extendedGCD :: a - a - (a,a,a)

While I'm wholeheartedly in favor of the Euclidean algorithm idea, I
suspect that more structure (i.e. separating it out to another class)
could be useful, for instance, formal power series' over Z are integral
domains, but are not a Euclidean domain because their residue classes
aren't computable by a finite process. Various esoteric rings like
Z[sqrt(k)] for various positive and negative integer k can also make
this dependence explode, though they're probably too rare to matter.

 TODO: quot, rem partially defined.  Explain.
 The default definition of extendedGCD above should not be taken as
 canonical (unlike most default definitions); for some Integral
 instances, the algorithm could diverge, might not satisfy the laws
 above, etc.
 TODO: (/) is only partially defined.  How to specify?  Add a member
   isInvertible :: a - Bool?
 Typical examples include rationals, the real numbers, and rational
 functions (ratios of polynomials).

It's too easy to make it a partial function to really consider this,
but if you wanted to go over the top (and you don't) you want the
multiplicative group of units to be the type of the argument (and
hence result) of recip.

  class (Num a, Additive b) = Powerful a b where
  ...
 I don't know interesting examples of this structure besides the
 instances above defined above and the Floating class below.
 "Positive" is a type constructor that asserts that its argument is =
 0; "positive" makes this assertion.  I am not sure how this will
 interact with defaulting arguments so that one can write
 
   x ^ 5
 
 without constraining x to be of Fractional type.

What you're really trying to capture here is the (right?) Z-module-like
structure of the multiplicative monoid in a commutative ring. There are
some weird things going on here I'm not sure about, namely:

(1) in an arbitary commutative ring (or multiplicative semigroup),
the function can (at best) be defined as
(^) :: ring - NaturalNumbers - ring
That is, only the natural numbers can act on ring to produce
an exponentiation-like operation.

Re: A sample revised prelude for numeric classes

2001-02-11 Thread Joe English


Dylan Thurston wrote:

 I've started writing up a more concrete proposal for what I'd like the
 Prelude to look like in terms of numeric classes.

I like this proposal a lot.  The organization is closer to
traditional mathematical structures than the current
Prelude, but not as intimidating as Mechveliani's
Basic Algebra Proposal.  A very nice balance, IMO.

A couple of requests:

  module Lattice where
  class Lattice a where
  meet, join :: a - a - a

Could this be split into

class SemiLattice a where
join :: a - a - a

and

class (SemiLattice a) = Lattice a where
meet :: a - a - a

I run across a lot of structures which could usefully
be modeled as semilattices, but lack a 'meet' operation.

 It would be reasonable to make Ord a
 subclass of this, but it would probably complicate the class heirarchy
 too much for the gain.

In a similar vein, I'd really like to see the Ord class
split up:

class PartialOrder a where
(), ()   :: a - a - Bool

class (Eq a, PartialOrder a) = Ord a where
compare:: a - a - Ordering
(=), (=) :: a - a - Bool
max, min   :: a - a - a

Perhaps it would make sense for PartialOrder to be a
superclass of Lattice?


--Joe English

  [EMAIL PROTECTED]

___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe



Re: A sample revised prelude for numeric classes

2001-02-11 Thread William Lee Irwin III

At 2001-02-11 14:42, Dylan Thurston wrote:
 I've started writing up a more concrete proposal for what I'd like the
 Prelude to look like in terms of numeric classes.  Please find it
 attached below.  It's still a draft and rather incomplete, but please
 let me know any comments, questions, or suggestions.

On Sun, Feb 11, 2001 at 04:03:37PM -0800, Ashley Yakeley wrote:
 Apologies if this has been discussed and I missed it. When it comes to 
 writing a 'geek' prelude, what was wrong with the Basic Algebra Proposal 
 found in ftp://ftp.botik.ru/pub/local/Mechveliani/basAlgPropos/ ? 
 Perhaps it could benefit from multi-parameter classes?

I'm not sure if there is anything concrete wrong with it, in fact, I'd
like to see it made into a Prelude, but there are several reasons why
I don't think it's being discussed here in the context of an alternative
for a Prelude.

(1) It's widely considered too complex and/or too mathematically
involved for the general populace (or whatever semblance thereof
exists within the Haskell community).
(2) As a "Geek Prelude", it's considered to have some aesthetic
and/or usability issues.
(3) For persons as insane as myself, it's actually not radical enough.

My commentary on it thus far is that I see it as high-quality software
that could not only already serve as a "Geek Prelude" for many users, but
upon which could also be based implementations and designs of future
"Geek Preludes". The fact that no one has discussed it is probably due
to a desire not to return to previous flamewars, but it should almost
definitely be discussed as a reference point.

I've actually been hoping that Mechveliani would chime in and comment on
the various ideas, since he's actually already been through the motions
of implementing an alternative Prelude and seen what sort of
difficulties arise from actually trying to do these things various ways.


Cheers,
Bill

___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe



Re: A sample revised prelude for numeric classes

2001-02-11 Thread Dylan Thurston

Thanks for the comments!

On Mon, Feb 12, 2001 at 12:26:35AM +, Marcin 'Qrczak' Kowalczyk wrote:
 I don't like the fact that there is no Powerful Integer Integer.

Reading this, it occurred to me that you could explictly declare an
instance of Powerful Integer Integer and have everything else work.

 Then the second argument of (^) is always arbitrary RealIntegral,

Nit: the second argument should be an Integer, not an arbitrary
RealIntegral.

   class (Real a, Floating a) = RealFrac a where
   -- lifted directly from Haskell 98 Prelude
   properFraction   :: (Integral b) = a - (b,a)
   truncate, round  :: (Integral b) = a - b
   ceiling, floor   :: (Integral b) = a - b
 
 Should be RealIntegral instead of Integral.

Yes.  I'd actually like to make it Integer, and let the user compose
with fromInteger herself.

 Perhaps RealIntegral should be called Integral, and your Integral
 should be called somewhat differently.

Perhaps.  Do you have suggestions for names?  RealIntegral is what
naive users probably want, but Integral is what mathematicians would
use (and call something like an integral domain).

   class (Real a, Integral a) = RealIntegral a where
   quot, rem:: a - a - a   
   quotRem  :: a - a - (a,a)
  
 -- Minimal definition: toInteger
 
 You forgot toInteger.

Oh, right.  I actually had it and then deleted it.  On the one hand,
it feels very implementation-specific to me, comparable to the
decodeFloat routines (which are useful, but not generally
applicable).  On the other hand, I couldn't think of many examples
where I really wouldn't want that operation (other than monadic
numbers, that, say, count the number of operations), and I couldn't
think of a better place to put it.

You'll notice that toRational was similarly missing.

My preferred solution might still be the Convertible class I mentioned
earlier.  Recall it was
  class Convertible a b where
  convert :: a - b
maybe with another class like
  class (Convertible a Integer) = ConvertibleToInteger a where
  toInteger :: a - Integer
  toInteger = convert
if the restrictions on instance contexts remain.  Convertible a b
should indicate that a can safely be converted to b without losing any
information and maintaining relevant structure; from this point of 
view, its use would be strictly limited.  (But what's relevant?)

I'm still undecided here.

Best,
Dylan Thurston

___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe



Re: A sample revised prelude for numeric classes

2001-02-11 Thread Fergus Henderson

On 11-Feb-2001, Dylan Thurston [EMAIL PROTECTED] wrote:
  class (Num a) = Integral a where
  div, mod :: a - a - a
  divMod :: a - a - (a,a)
  gcd, lcm :: a - a - a
  extendedGCD :: a - a - (a,a,a)
 
   -- Minimal definition: divMod or (div and mod)
   --   and extendedGCD, if the provided definition does not work
  div a b | (d,_) - divMod a b = d
  mod a b | (_,m) - divMod a b = m
  divMod a b = (div a b, mod a b)
  gcd a b | (_,_,g) - extendedGCD a b = g
  extendedGCD a b = ... -- insert Euclid's algorithm here
  lcm a b = (a `div` gcd a b) * b
 
 Integral has the mathematical structure of a unique factorization
 domain, satisfying the laws
 
   a * b === b * a
   (div a b) * b + (mod a b) === a
   mod (a+k*b) b === mod a b
 a `div` gcd a b === zero
 gcd a b === gcd b a
 gcd (a + k*b) b === gcd a b
   a*c + b*d === g where (c, d, g) = extendedGCD a b
 
 TODO: quot, rem partially defined.  Explain.
 The default definition of extendedGCD above should not be taken as
 canonical (unlike most default definitions); for some Integral
 instances, the algorithm could diverge, might not satisfy the laws
 above, etc.

In that case, I think it might be better to not provide it as a
default, and instead to provide a function called say
`euclid_extendedGCD'; someone defining an instance can then

extendedGCD = euclid_extendedGCD

if that is appropriate.  It's so much easier to find bugs in code that you
did write rather than bugs which are caused by what you *didn't* write.

Of course this is not so effective if we keep the awful Haskell 98
rule that instance methods always default to bottom if not defined;
but even if that rule is not changed, compilers can at least warn
about that case.

  class (Num a, Additive b) = Powerful a b where
  (^) :: a - b - a

I don't like the name.  Plain `Pow' would be better, IMHO.

Apart from those two points, I quite like this proposal,
at least at first glance.

-- 
Fergus Henderson [EMAIL PROTECTED]  |  "I have always known that the pursuit
|  of excellence is a lethal habit"
WWW: http://www.cs.mu.oz.au/~fjh  | -- the last words of T. S. Garp.

___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe



Re: A sample revised prelude for numeric classes

2001-02-11 Thread Dylan Thurston

On Sun, Feb 11, 2001 at 06:48:42PM -0800, William Lee Irwin III wrote:
 There is an additional property of zero being neglected here, namely
 that it is an annihilator. That is,
 
   zero * x === zero
   x * zero === zero

It follows:

  zero * x === (one - one) * x === one * x - one * x === x - x === zero

 Again, it's probably a reasonable compromise not to accommodate
 nonassociative algebras, though an important application of them
 lies within graphics, namely 3-vectors with the cross product.

Agreed that non-associative algebras are useful, but I feel that they
should have a different symbol.

   class (Num a) = Integral a where
   div, mod :: a - a - a
   divMod :: a - a - (a,a)
   gcd, lcm :: a - a - a
   extendedGCD :: a - a - (a,a,a)
 
 While I'm wholeheartedly in favor of the Euclidean algorithm idea, I
 suspect that more structure (i.e. separating it out to another class)
 could be useful, for instance, formal power series' over Z are integral
 domains, but are not a Euclidean domain because their residue classes
 aren't computable by a finite process. Various esoteric rings like
 Z[sqrt(k)] for various positive and negative integer k can also make
 this dependence explode, though they're probably too rare to matter.

technical math
I tried to write the definitions in a way that could be defined for
any unique factorization domain, not necessarily Euclidean: just take
the two numbers, write them as a unit times prime factors in canonical
form, and take the product of the common factors and call that the
GCD.  On reflection, extendedGCD probably isn't easy to write in
general.

What operations would you propose to encapsulate an integral domain
(rather than a UFD)?

Formal power series over Z are an interesting example; I'll think
about it.  On first blush, it seems like if you represented them as
lazy lists you might be able to compute the remainder term by term.
/technical math

  TODO: quot, rem partially defined.  Explain.
  The default definition of extendedGCD above should not be taken as
  canonical (unlike most default definitions); for some Integral
  instances, the algorithm could diverge, might not satisfy the laws
  above, etc.
  TODO: (/) is only partially defined.  How to specify?  Add a member
isInvertible :: a - Bool?
  Typical examples include rationals, the real numbers, and rational
  functions (ratios of polynomials).
 
 It's too easy to make it a partial function to really consider this,
 but if you wanted to go over the top (and you don't) you want the
 multiplicative group of units to be the type of the argument (and
 hence result) of recip.

Yes.  I considered and rejected that.  But it would be nice to let
callers check whether the division will blow up, and that's not
possible for classes that aren't members of Eq.

But I suppose that's the whole point.  For computable reals, the way I
would compute 1/(very small number) would be to look at (very small
number) more and more closely to figure out on which side of 0 it lay;
if it actually were zero, the program would loop.  I think programs
that want to avoid this have to take type-specific steps (in this
case, cutting off the evaluation at a certain point.)

 What you're really trying to capture here is the (right?) Z-module-like
 structure of the multiplicative monoid in a commutative ring. There are
 some weird things going on here I'm not sure about, namely:

Right.

   (3) Under some condition I don't seem to be able to formulate
   offhand, one can do
   (^) :: ring - ring - ring
   Now the ring (or perhaps more generally some related ring)
   acts on ring to produce an expontiation operation like what
   is typically thought of for real numbers. Anyone with good
   ideas as to what the appropriate conditions are here, please
   speak up.
   (Be careful, w ^ z = exp (z * log w) behaves badly for w  0
   on the reals.)

For complex numbers as well, this operation has problems because of
branch cuts.  It does satisfy that identity I mentioned, but is not
continuous in the first argument.

It is more common to see functions like exp be well defined (for more
general additive groups) than to see the full (^) be defined.

   class (Num a, Ord a) = Real a where
   abs:: x - x
   signum :: x - x
 
 I'm not convinced that Real is a great name for this, or that this
 is really the right type for all this stuff. I'd still like to see
 abs and signum generalized to vector spaces.

After thinking about this, I decided that I would be happy calling the
comparable operation on vector spaces "norm":
a) it's compatible with mathematical usage
b) it keeps the Prelude itself simple.
It's unfortunate that the operation for complex numbers can't be
called "abs", but I think it's reasonable.

 good stuff on lattices deleted ...and Ord defines a partial order
 (and hence 

Re: A sample revised prelude for numeric classes

2001-02-11 Thread Brian Boutel

Dylan Thurston wrote:
 
 I've started writing up a more concrete proposal for what I'd like the
 Prelude to look like in terms of numeric classes.  Please find it
 attached below.  It's still a draft and rather incomplete, but please
 let me know any comments, questions, or suggestions.
 


This is a good basis for discussion, and it helps to see something
concrete. 

Here are a few comments:

 Thus these laws should be interpreted as guidelines rather than
 absolute rules.  In particular, the compiler is not allowed to use
 them.  Unless stated otherwise, default definitions should also be
 taken as laws.

Including laws was discussed very early in the development of the
language, but was rejected. IIRC Miranda had them. The argument against
laws was that their presence might mislead users into the assumption
that they did hold, yet if they were not enforcable then they might not
hold and that could have serious consequences. Also, some laws do not
hold in domains with bottom, e.g. a + (negate a) === 0 is only true if a
is not bottom. 


 class (Additive a) = Num a where
 (*) :: a - a - a
 one :: a
 fromInteger :: Integer - a

   -- Minimal definition: (*), one
 fromInteger 0 = zero
 fromInteger n | n  0 = negate (fromInteger (-n))
 fromInteger n | n  0 = reduceRepeat (+) one n

This definition requires both Eq and Ord!!!



As does this one:

 class (Num a, Additive b) = Powerful a b where
 (^) :: a - b - a
 instance (Num a) = Powerful a (Positive Integer) where
 a ^ 0 = one
 a ^ n = reduceRepeated (*) a n
 instance (Fractional a) = Powerful a Integer where
 a ^ n | n  0 = recip (a ^ (negate n))
 a ^ n = a ^ (positive n)


and several others further down. 


 (4) In some cases, the hierarchy is not finely-grained enough:
 operations that are often defined independently are lumped
 together.  For instance, in a financial application one might want
 a type "Dollar", or in a graphics application one might want a
 type "Vector".  It is reasonable to add two Vectors or Dollars,
 but not, in general, reasonable to multiply them.  But the
 programmer is currently forced to define a method for (*) when she
 defines a method for (+).

Why do you stop at allowing addition on Dollars and not include
multiplication by a scalar? Division is also readily defined on Dollar
values, with a scalar result, but this, too, is not available in the
proposal. 

Having Units as types, with the idea of preventing adding Apples to
Oranges, or Dollars to Roubles, is a venerable idea, but is not in
widespread use in actual programming languages. Why not?

Vectors, too, can be multiplied, producing both scalar- and
vector-products.

It seems that you are content with going as far as the proposal permits,
though you cannot define, even within the revised Class system, all the
common and useful operations on these types. This is the same situation
as with Haskell as it stands. The question is whether the (IMHO)
marginal increase in flexibility is worth the cost.

This is not an argument for not separating Additive from Num, but it
does weaken the argument for doing it.

--brian

___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe



Re: A sample revised prelude for numeric classes

2001-02-11 Thread William Lee Irwin III

On Sun, Feb 11, 2001 at 10:56:29PM -0500, Dylan Thurston wrote:
 It follows:
   zero * x === (one - one) * x === one * x - one * x === x - x === zero

Heh, you've caught me sleeping. =)

On Sun, Feb 11, 2001 at 10:56:29PM -0500, Dylan Thurston wrote:
 I tried to write the definitions in a way that could be defined for
 any unique factorization domain, not necessarily Euclidean: just take
 the two numbers, write them as a unit times prime factors in canonical
 form, and take the product of the common factors and call that the
 GCD.  On reflection, extendedGCD probably isn't easy to write in
 general.

Well, factorizing things in various UFD's doesn't sound easy to me, but
at this point I'm already having to do some reaching for counterexamples
of practical programs where this matters. It could end up being a useless
class method in some instances, so I'm wary of it.

On Sun, Feb 11, 2001 at 10:56:29PM -0500, Dylan Thurston wrote:
 What operations would you propose to encapsulate an integral domain
 (rather than a UFD)?

I'm not necessarily proposing a different set of operations to
encapsulate them, but rather that gcd and cousins be split off into
another subclass. Your design decisions in general appear to be
striking a good chord, so I'll just bring up the idea and let you
decide whether it should be done that way and so on.

On Sun, Feb 11, 2001 at 10:56:29PM -0500, Dylan Thurston wrote:
 Formal power series over Z are an interesting example; I'll think
 about it.  On first blush, it seems like if you represented them as
 lazy lists you might be able to compute the remainder term by term.

Consider taking of the residue of a truly infinite member of Z[[x]]
mod an ideal generated by a polynomial, e.g. 1/(1-x) mod (1+x^2).
You can take the residue of each term of 1/(1-x), so x^(2n) - (-1)^n
and x^(2n+1) - (-1)^n x, but you end up with an infinite number of
(nonzero!) residues to add up and hence encounter the troubles with
processes not being finite that I mentioned.

On Sun, Feb 11, 2001 at 06:48:42PM -0800, William Lee Irwin III wrote:
  (3) Under some condition I don't seem to be able to formulate
  offhand, one can do
  (^) :: ring - ring - ring
  Now the ring (or perhaps more generally some related ring)
  acts on ring to produce an expontiation operation like what
  is typically thought of for real numbers. Anyone with good
  ideas as to what the appropriate conditions are here, please
  speak up.
  (Be careful, w ^ z = exp (z * log w) behaves badly for w  0
  on the reals.)

On Sun, Feb 11, 2001 at 10:56:29PM -0500, Dylan Thurston wrote:
 For complex numbers as well, this operation has problems because of
 branch cuts.  It does satisfy that identity I mentioned, but is not
 continuous in the first argument.
 It is more common to see functions like exp be well defined (for more
 general additive groups) than to see the full (^) be defined.

I think it's nice to have the Cauchy principal value versions of things
floating around.  I know at least that I've had call for using the CPV
of exponentiation (and it's not hard to contrive an implementation),
but I'm almost definitely an atypical user. (Note, (**) does this today.)

On Sun, Feb 11, 2001 at 06:48:42PM -0800, William Lee Irwin III wrote:
 I'm not convinced that Real is a great name for this, or that this
 is really the right type for all this stuff. I'd still like to see
 abs and signum generalized to vector spaces.

On Sun, Feb 11, 2001 at 10:56:29PM -0500, Dylan Thurston wrote:
 After thinking about this, I decided that I would be happy calling the
 comparable operation on vector spaces "norm":
 a) it's compatible with mathematical usage
 b) it keeps the Prelude itself simple.
 It's unfortunate that the operation for complex numbers can't be
 called "abs", but I think it's reasonable.

I'm not entirely sure, but I think part of the reason this hasn't been
done already is because it's perhaps painful to statically type
dimensionality in vector spaces. On the other hand, assuming that the
user has perhaps contrived a representation satisfactory to him or her,
defining a class on the necessary type constructor shouldn't be tough
at all.

In a side note, it seems conventional to use abs and signum on complex
numbers (and functions), and also perhaps the same symbol as abs for
the norm on vectors and vector functions. It seems the distinction
drawn is that abs is definitely pointwise and the norm more often does
some sort of shenanigan like L^p norms etc. How much of this convention
should be preserved seems like a design decision, but perhaps one that
should be made explicit.

On Sun, Feb 11, 2001 at 06:48:42PM -0800, William Lee Irwin III wrote:
 good stuff on lattices deleted ...and Ord defines a partial order
 (and hence induces Eq) on a type.

On Sun, Feb 11, 2001 at 10:56:29PM -0500, Dylan Thurston wrote:
 I think that 

Re: A sample revised prelude for numeric classes

2001-02-11 Thread Tom Pledger

Brian Boutel writes:
 :
 | Having Units as types, with the idea of preventing adding Apples to
 | Oranges, or Dollars to Roubles, is a venerable idea, but is not in
 | widespread use in actual programming languages. Why not?

There was a pointer to some good papers on this in a previous
discussion of units and dimensions:

http://www.mail-archive.com/haskell@haskell.org/msg04490.html

The main complication is that the type system needs to deal with
integer exponents of dimensions, if it's to do the job well.

For example, it should be OK to divide an acceleration (length *
time^-2) by a density (mass * length^-3).  Such things may well occur
as subexpressions of something more intuitive, and it's undesirable to
spell out all the anticipated dimension types in a program (a Haskell
98 program, for example) because:

  - Only an arbitrary finite number would be covered, and

  - The declarations would contain enough un-abstracted clichs to
bring a tear to the eye.
instance Mul Double (Dim_L Double) (Dim_L Double)
instance Mul (Dim_L Double) (Dim_per_T Double) (Dim_L_per_T Double)
etc.

Regards,
Tom

___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe



Re: A sample revised prelude for numeric classes

2001-02-11 Thread William Lee Irwin III

On Mon, Feb 12, 2001 at 05:24:37PM +1300, Brian Boutel wrote:
 Including laws was discussed very early in the development of the
 language, but was rejected. IIRC Miranda had them. The argument against
 laws was that their presence might mislead users into the assumption
 that they did hold, yet if they were not enforcable then they might not
 hold and that could have serious consequences. Also, some laws do not
 hold in domains with bottom, e.g. a + (negate a) === 0 is only true if a
 is not bottom. 

I actually think it would be useful to have them and optionally
dynamically enforce them, or at least whichever ones are computable, as
a compile-time option. This would be _extremely_ useful for debugging
purposes, and I, at the very least, would use it. I think Eiffel does
something like this, can anyone else comment?

This, of course, is a language extension, and so probably belongs in
a different discussion from the rest of all this.

Dylan Thurston wrote:
 class (Additive a) = Num a where
 (*) :: a - a - a
 one :: a
 fromInteger :: Integer - a
   -- Minimal definition: (*), one
 fromInteger 0 = zero
 fromInteger n | n  0 = negate (fromInteger (-n))
 fromInteger n | n  0 = reduceRepeat (+) one n

On Mon, Feb 12, 2001 at 05:24:37PM +1300, Brian Boutel wrote:
 This definition requires both Eq and Ord!!!

Only on Integer, not on a.

On Mon, Feb 12, 2001 at 05:24:37PM +1300, Brian Boutel wrote:
 As does this one:

Dylan Thurston wrote:
 class (Num a, Additive b) = Powerful a b where
 (^) :: a - b - a
 instance (Num a) = Powerful a (Positive Integer) where
 a ^ 0 = one
 a ^ n = reduceRepeated (*) a n
 instance (Fractional a) = Powerful a Integer where
 a ^ n | n  0 = recip (a ^ (negate n))
 a ^ n = a ^ (positive n)

I should note that both of these definitions which require Eq and
Ord only require it on Integer.

On Mon, Feb 12, 2001 at 05:24:37PM +1300, Brian Boutel wrote:
 and several others further down. 

I'm not sure which ones you hit on, though I'm sure we'd all be more
than happy to counter-comment on them or repair the inadequacies.

Dylan Thurston wrote:
 (4) In some cases, the hierarchy is not finely-grained enough:
 operations that are often defined independently are lumped
 together.  For instance, in a financial application one might want
 a type "Dollar", or in a graphics application one might want a
 type "Vector".  It is reasonable to add two Vectors or Dollars,
 but not, in general, reasonable to multiply them.  But the
 programmer is currently forced to define a method for (*) when she
 defines a method for (+).

On Mon, Feb 12, 2001 at 05:24:37PM +1300, Brian Boutel wrote:
 Why do you stop at allowing addition on Dollars and not include
 multiplication by a scalar? Division is also readily defined on Dollar
 values, with a scalar result, but this, too, is not available in the
 proposal. 

I can comment a little on this, though I can't speak for someone else's
design decisions. In general, the results of division and multiplication
for units have a different result type than those of the arguments. This
makes defining them by type class overloading either require existential
wrappers or makes them otherwise difficult or impossible to define.

On Mon, Feb 12, 2001 at 05:24:37PM +1300, Brian Boutel wrote:
 Having Units as types, with the idea of preventing adding Apples to
 Oranges, or Dollars to Roubles, is a venerable idea, but is not in
 widespread use in actual programming languages. Why not?

I'm probably even less qualified to comment on this, but I'll conjecture
that the typing disciplines of most languages make it impractical. I
suspect it could be possible in Haskell.

On Mon, Feb 12, 2001 at 05:24:37PM +1300, Brian Boutel wrote:
 Vectors, too, can be multiplied, producing both scalar- and
 vector-products.

Exterior and inner products both encounter much the same troubles as
defining arithmetic on types with units attached, with the additional
complication that statically typing dimensionality is nontrivial.

On Mon, Feb 12, 2001 at 05:24:37PM +1300, Brian Boutel wrote:
 It seems that you are content with going as far as the proposal permits,
 though you cannot define, even within the revised Class system, all the
 common and useful operations on these types. This is the same situation
 as with Haskell as it stands. The question is whether the (IMHO)
 marginal increase in flexibility is worth the cost.
 This is not an argument for not separating Additive from Num, but it
 does weaken the argument for doing it.

I'm not convinced of this, though I _am_ convinced that a general
framework for units would probably be useful to have in either a
standard or add-on library distributed with Haskell, or perhaps to
attempt to address units even within the standard Prelude if it's
simple enough. Are you up to perhaps taking a stab at this? Perhaps
if you tried it within the framework 

Re: A sample revised prelude for numeric classes

2001-02-11 Thread Ashley Yakeley

At 2001-02-11 21:18, Tom Pledger wrote:

The main complication is that the type system needs to deal with
integer exponents of dimensions, if it's to do the job well.

Very occasionally non-integer or 'fractal' exponents of dimensions are 
useful. For instance, geographic coastlines can be measured in km ^ n, 
where 1 = n  2. This doesn't stop the CIA world factbook listing all 
coastline lengths in straight kilometres, however.

More unit weirdness occurs with logarithms. For instance, if y and x are 
distances, log (y/x) = log y - log x. Note that 'log x' is some number + 
log (metre). Strange, huh?

Interestingly, in C++ you can parameterise types by values. For instance:

--
// Mass, Length and Time
template long M,long L,long T
class Unit
 {
 public:
 double mValue;

 inline explicit Unit(double value)
  {
  mValue = value;
  }
 };

template long M,long L,long T
UnitM,L,T operator + (UnitM,L,T a,UnitM,L,T b)
 {
 return UnitM,L,T(a.mValue + b.mValue);
 }

template long Ma,long La,long Ta,long Mb,long Lb,long Tb
UnitMa+Mb,La+Lb,Ta+Tb operator * (UnitMa,La,Ta a,UnitMb,Lb,Tb b)
 {
 return UnitMa+Mb,La+Lb,Ta+Tb(a.mValue * b.mValue);
 }

// etc.

int main()
 {
 Unit0,1,0 oneMetre(1);
 Unit0,1,0 twoMetres = oneMetre + oneMetre;
 Unit0,2,0 oneSquareMetre = oneMetre * oneMetre;
 }
--

Can you do this sort of thing in Haskell?


-- 
Ashley Yakeley, Seattle WA


___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe



Re: A sample revised prelude for numeric classes

2001-02-11 Thread William Lee Irwin III

At 2001-02-11 21:18, Tom Pledger wrote:
The main complication is that the type system needs to deal with
integer exponents of dimensions, if it's to do the job well.

On Sun, Feb 11, 2001 at 10:16:02PM -0800, Ashley Yakeley wrote:
 Very occasionally non-integer or 'fractal' exponents of dimensions are 
 useful. For instance, geographic coastlines can be measured in km ^ n, 
 where 1 = n  2. This doesn't stop the CIA world factbook listing all 
 coastline lengths in straight kilometres, however.

This is pretty rare, and it's also fairly tough to represent points in
spaces of fractional dimension. I'll bet the sorts of complications
necessary to do so would immediately exclude it from consideration in
the design of a standard library, but nevertheless would be interesting
to hear about. Can you comment further on this?

On Sun, Feb 11, 2001 at 10:16:02PM -0800, Ashley Yakeley wrote:
 More unit weirdness occurs with logarithms. For instance, if y and x are 
 distances, log (y/x) = log y - log x. Note that 'log x' is some number + 
 log (metre). Strange, huh?

If you (or anyone else) could comment on what sorts of units would be
appropriate for the result type of a logarithm operation, I'd be glad to
hear it. I don't know what the result type of this example is supposed
to be if the units of a number are encoded in the type.

On Sun, Feb 11, 2001 at 10:16:02PM -0800, Ashley Yakeley wrote:
 Interestingly, in C++ you can parameterise types by values. For instance:
[interesting C++ example elided]
 Can you do this sort of thing in Haskell?

No, in general I find it necessary to construct some sort of set of
types parallel to the actual data type, define some sort of existential
data type encompassing the set of all types which can represent one of
those appropriate values, and "lift" things to that type by means of
sample arguments. I usually like ensuring that the types representing
things like integers never actually have any sort of data manifest,
i.e. the sample arguments are always undefined. This is a bit awkward.

I think Okasaki's work on square matrices and perhaps some other ideas
should be exploited for this sort of thing, as there is quite a bit of
opposition to the usage of sample arguments. I'd like to see a library
for vector spaces based on similar ideas. I seem to be caught up in
other issues caused by mucking with fundamental data types' definitions,
my working knowldedge of techniques like Okasaki's is insufficient for
the task, and my design concepts are probably too radical for general
usage, so I'm probably not the man for the job, though I will very
likely take a stab at such a beast for my own edification.


Cheers,
Bill

___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe



Re: A sample revised prelude for numeric classes

2001-02-11 Thread Marcin 'Qrczak' Kowalczyk

Mon, 12 Feb 2001 17:24:37 +1300, Brian Boutel [EMAIL PROTECTED] pisze:

  class (Additive a) = Num a where
  (*) :: a - a - a
  one :: a
  fromInteger :: Integer - a
 
-- Minimal definition: (*), one
  fromInteger 0 = zero
  fromInteger n | n  0 = negate (fromInteger (-n))
  fromInteger n | n  0 = reduceRepeat (+) one n
 
 This definition requires both Eq and Ord!!!

Only Eq Integer and Ord Integer, which are always there.

 Why do you stop at allowing addition on Dollars and not include
 multiplication by a scalar?

Perhaps because there is no good universal type for (*).
Sorry, it would have to have a different symbol.

 Having Units as types, with the idea of preventing adding Apples to
 Oranges, or Dollars to Roubles, is a venerable idea, but is not in
 widespread use in actual programming languages. Why not?

It does not scale to more general cases. (m/s) / (s) = (m/s^2),
so (/) would have to have the type (...) = a - b - c, which is not
generally usable because of ambiguities. Haskell's classes are not
powerful enough to define full algebra of units.

 It seems that you are content with going as far as the proposal permits,
 though you cannot define, even within the revised Class system, all the
 common and useful operations on these types. This is the same situation
 as with Haskell as it stands. The question is whether the (IMHO)
 marginal increase in flexibility is worth the cost.

The Prelude class system requires a compromise. There is no single
design which accommodates all needs because Haskell's classes are
not powerful enough to unify all levels of generality in a single
class operation. And even if it was possible, it would be awkward
to use in simpler cases.

-- 
 __("  Marcin Kowalczyk * [EMAIL PROTECTED] http://qrczak.ids.net.pl/
 \__/
  ^^  SYGNATURA ZASTPCZA
QRCZAK


___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe



Re: A sample revised prelude for numeric classes

2001-02-11 Thread Marcin 'Qrczak' Kowalczyk

Sun, 11 Feb 2001 22:27:53 -0500, Dylan Thurston [EMAIL PROTECTED] pisze:

 Reading this, it occurred to me that you could explictly declare an
 instance of Powerful Integer Integer and have everything else work.

No, because it overlaps with Powerful a Integer (the constraint on a
doesn't matter for determining if it overlaps).

  Then the second argument of (^) is always arbitrary RealIntegral,
 
 Nit: the second argument should be an Integer, not an arbitrary
 RealIntegral.

Of course not. (2 :: Integer) ^ (i :: Int) makes perfect sense.

  You forgot toInteger.
 
 Oh, right.  I actually had it and then deleted it.  On the one hand,
 it feels very implementation-specific to me, comparable to the
 decodeFloat routines

It is needed for conversions (fromIntegral in particular).

   class Convertible a b where
   convert :: a - b
 maybe with another class like
   class (Convertible a Integer) = ConvertibleToInteger a where
   toInteger :: a - Integer
   toInteger = convert

This requires to write a Convertible instance in addition to
ConvertibleToInteger, where currently mere toInteger in Integral
suffices.

Since Convertible must be defined separately for each pair of types
(otherwise instances would easily overlap), it's not very useful for
numeric conversions. Remember that there are a lot of numeric types
in the FFI: Int8, Word16, CLong, CSize. It does not provide anything
in this area so should not be required to define instances there.

After a proposal is developed, please check how many instances one
has to define to make a type the same powerful as Int, and is it
required to define methods irrelevant to non-mathematical needs.
basAlgPropos fails badly in this criterion.

 Convertible a b should indicate that a can safely be converted to
 b without losing any information and maintaining relevant structure;

So fromInteger does not require Convertible, which is inconsistent
with toInteger. Sorry, I am against Convertible in Prelude - tries
to be too general, which makes it inappropriate.

-- 
 __("  Marcin Kowalczyk * [EMAIL PROTECTED] http://qrczak.ids.net.pl/
 \__/
  ^^  SYGNATURA ZASTPCZA
QRCZAK


___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe