Revised numerical prelude, version 0.02

Here's a revision of the numerical prelude. Many thanks to all who helped. Changes include: * Removed "Powerful", replacing it with (^) in Num and (**) in Real. * Fixed numerous typos * Removed gcd and co. from Integral * Added shortcomings & limitation of scope * Added SmallIntegral, SmallReal * wrote skeleton VectorSpace, PowerSeries * Added framework to make it run under hugs. There are some usability issues. Any comments welcome! Best, Dylan Thurston

Tue, 13 Feb 2001 18:32:21 -0500, Dylan Thurston
I'd like to copy this over to this revised library. But the numeric constants have to be wrapped in explicit calls to fromInteger.
ghc's docs (the CVS version) say that -fno-implicit-prelude causes numeric literals to use whatever fromInteger is in scope. AFAIR it worked at some time, but it does not work anymore! BTW, why not let 'import MyPrelude as Prelude' work that way? -- __("< Marcin Kowalczyk * qrczak@knm.org.pl http://qrczak.ids.net.pl/ \__/ ^^ SYGNATURA ZASTÊPCZA QRCZAK

Tue, 13 Feb 2001 18:32:21 -0500, Dylan Thurston
Here's a revision of the numerical prelude.
I like it!
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
These should be SmallIntegral.
For an instance of RealIntegral a, it is expected that a `quot` b will round towards minus infinity and a `div` b will round towards 0.
The opposite.
class (Real a) => SmallReal a where toRational :: a -> Rational class (SmallReal a, RealIntegral a) => SmallIntegral a where toInteger :: a -> Integer
These two classes exist to allow convenient conversions, primarily between the built-in types. These classes are "small" in the sense that they can be converted to integers (resp. rationals) without loss of information.
I find names of these classes unclear: Integer is not small integral, it's big integral (as opposed to Int)! :-) Perhaps these classes should be called Real and Integral, with different names for current Real and Integral. But I don't have a concrete proposal. -- __("< Marcin Kowalczyk * qrczak@knm.org.pl http://qrczak.ids.net.pl/ \__/ ^^ SYGNATURA ZASTÊPCZA QRCZAK

On Wed, Feb 14, 2001 at 09:53:16PM +0000, Marcin 'Qrczak' Kowalczyk wrote:
Tue, 13 Feb 2001 18:32:21 -0500, Dylan Thurston
pisze: Here's a revision of the numerical prelude. I like it!
I'd like to start using something like this in my programs. What are the chances that the usability issues will be addressed? (The main one is all the fromInteger's, I think.)
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 These should be SmallIntegral.
It could be either one, since they produce the type on output (it calls fromInteger). I changed it, on the theory that it might be less confusing. But it should inherit from SmallReal. (Oh, except then RealFloat inherits from SmallReal, which it shouldn't have to. Gah.)
For an instance of RealIntegral a, it is expected that a `quot` b will round towards minus infinity and a `div` b will round towards 0. The opposite.
Thanks.
class (Real a) => SmallReal a where toRational :: a -> Rational class (SmallReal a, RealIntegral a) => SmallIntegral a where toInteger :: a -> Integer ... I find names of these classes unclear: Integer is not small integral, it's big integral (as opposed to Int)! :-)
I agree, but I couldn't think of anything better. I think this end of the heirarchy (that inherits from Real) could use some more work. RealIntegral and SmallIntegral could possibly be merged, except that it violates the principle of not combining semantically disparate operations in a single class. Best, Dylan Thurston

Dylan Thurston writes:
I'd like to start using something like this in my programs. What are the chances that the usability issues will be addressed? (The main one is all the fromInteger's, I think.)
Have you tried using your alternative Prelude with nhc98? Offhand, I couldn't be certain it would work, but I think nhc98 probably makes fewer assumptions about the Prelude than ghc. You will need something like import qualified Prelude as NotUsed import Dylan'sPrelude as Prelude in any module that wants to use your prelude. IIRC, nhc98 treats 'fromInteger' exactly as the qualified name 'Prelude.fromInteger', so in theory it should simply pick up your replacement definitions. (In practice, it might actually do the resolution of module 'as' renamings a little too early or late, but the easiest way to find out for certain is to try it.) Regards, Malcolm

Perhaps I mentioned that I use Haskell to teach compilation, since I think that functional structures are good not only for parsers, but for a legible semantics for virtual machines, for the code generators, etc. The main assignment was to write a syntactic converter from a Haskell-like language to Scheme, and the exam included such exercises as Find the type of fm in fm _ z [] = return z fm g z (a:aq) = g z a >>= \y->fm g y aq When I started correcting the exam, I thought I would jump out of the window. First 30 copies: The type of fm is ff -> b -> [c] -> b (with an appropriate constraint for the functional type ff). The result had for them the same type as the type of z. My inquiry proved beyond any doubt that my students are so conditioned by "C", that despite the fact that we worked with monads for several weeks, they *cannot imagine* that "return z" may mean something different than the value of "z". Any suggestions? [Yes, I have one! Stop teaching, find a more appropriate job, e.g., cultivate genetically modified, mutant tomatoes.]] Jerzy Karczmarczuk "C"-aen, Fran-"C"-e.

On Fri, 16 Feb 2001, Jerzy Karczmarczuk wrote:
My inquiry proved beyond any doubt that my students are so conditioned by "C", that despite the fact that we worked with monads for several weeks, they *cannot imagine* that "return z" may mean something different than the value of "z".
Any suggestions?
Perhaps the name "return" in the monadic definitions could be replaced by something more suggestive of an action? How about running a little experiment next time, with a new name, to see whether this would remove this unfortunate association with C-like "return" in the minds of your students? Jan

On Fri, 16 Feb 2001, Jerzy Karczmarczuk wrote:
[..]
fm _ z [] = return z fm g z (a:aq) = g z a >>= \y->fm g y aq
When I started correcting the exam, I thought I would jump out of the window. First 30 copies: The type of fm is
ff -> b -> [c] -> b
(with an appropriate constraint for the functional type ff). The result had for them the same type as the type of z.
My inquiry proved beyond any doubt that my students are so conditioned by "C", that despite the fact that we worked with monads for several weeks, they *cannot imagine* that "return z" may mean something different than the value of "z".
Any suggestions?
Not that it would help you much, but I also think that return is a rather confusing name for what might otherwise be called liftM0. Regards, Andreas. ------------------------------------------------------------------------ Andreas Gruenbacher gruenbacher@geoinfo.tuwien.ac.at Research Assistant Phone +43(1)58801-12723 Institute for Geoinformation Fax +43(1)58801-12799 Technical University of Vienna Cell phone +43(664)4064789

The problem is Haskell, not your student. Haskell undermines the meaning of 'return', which has the same meaning in C, C++, Java, and who knows whatelse. These languages use 'return' to refer to one part of the denotation of a function return (value) and Haskell uses 'return' to refer to two parts (value, store). These languages have been around forever; Haskell came late. These languages are imperative; Haskell is a wanna-be imperative language. The students know C'ish stuff (and I take it some Scheme); you teach Haskell to introduce them to functional and denotational thinking. That's laudable. It's great. Just don't expect your students to change deeply ingrained habits such as the 'return habit' in a few weeks. Instead, teach explicit store-passing style and do it again and again and again until they ask "isn't this a pattern that we should abstract out". Then show monads and apologize profusely for the abuse of the return syntax in Haskell. If they don't ask, chew them out near the end of the semester for being bad programmers who can't see a pattern when it bites their b...d. Not worth the money. Fired. :-) -- Matthias

Why should we change and not C?
Erik
----- Original Message -----
From: "Jan Skibinski"
On Fri, 16 Feb 2001, Jerzy Karczmarczuk wrote:
My inquiry proved beyond any doubt that my students are so conditioned by "C", that despite the fact that we worked with monads for several weeks, they *cannot imagine* that "return z" may mean something different than the value of "z".
Any suggestions?
Perhaps the name "return" in the monadic definitions could be replaced by something more suggestive of an action? How about running a little experiment next time, with a new name, to see whether this would remove this unfortunate association with C-like "return" in the minds of your students?
Jan
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Because C was first and you don't have the power to change them. -- Matthias

On 16-Feb-2001 Matthias Felleisen wrote: | | The problem is Haskell, not your student. | | Haskell undermines the meaning of 'return', which has the same meaning in | C, C++, Java, and who knows whatelse. These languages use 'return' to | refer to one part of the denotation of a function return (value) and | Haskell uses 'return' to refer to two parts (value, store). These languages | have been around forever; Haskell came late. These languages are | imperative; Haskell is a wanna-be imperative language. The denotation of a return command in a typical imperative language supplies a value and a store to a calling continuation, so why is the name not entirely appropriate? Joseph H. Fasel, Ph.D. email: jhf@lanl.gov Technology Modeling and Analysis phone: +1 505 667 7158 University of California fax: +1 505 667 2960 Los Alamos National Laboratory post: TSA-7 MS F609; Los Alamos, NM 87545

Another good exam question (Hmm!): What does last (last (map return [1..])) lastly return given that last (return (not True))? I also would prefer "unit". "return" makes sense for me as syntactic sugar in the context of a "do"-expression (and then please like an unary prefix-operat or with low binding power...). An alternative sugary would be "compute": When a monad represents a computation, "init" returns a computation with a result, not just the result: foo x = if x > 0 then compute x*x else compute -x*x By the way, an alternative for "do" would be "seq" (as in occam) to indicate that operations are sequenced: getLine = seq c <- readChar if c == '\n' then compute "" else seq l <- getLine compute c:l But such a discussion has probably already been taken place some years ago. It would be interesting for me to know the arguments that led to the choice of "return" (and "do"). Elke. --- "If you have nothing to say, don't do it here..." Elke Kasimir Skalitzer Str. 79 10997 Berlin (Germany) fon: +49 (030) 612 852 16 mail: elke.kasimir@catmint.de> see: http://www.catmint.de/elke for pgp public key see: http://www.catmint.de/elke/pgp_signature.html
participants (10)
-
Andreas Gruenbacher
-
Dylan Thurston
-
Elke Kasimir
-
Erik Meijer
-
Jan Skibinski
-
Jerzy Karczmarczuk
-
Joe Fasel
-
Malcolm Wallace
-
Matthias Felleisen
-
qrczak@knm.org.pl