declaring properties
Hi Y'all, please ignore this message if you have the impression that I am writing complete nonsense :-) I am wondering if it would be feasible to declare laws that are guaranteed to hold for some objects in a Haskell-like functional language. For example I would like to declare that (+) is commutative. This would have the benefit, that the compiler could optimize the parameter passing to a commutative function by not having to swap arguments on the stack: > is5 x = x == 5 could transform to > is5 x = 5 == x thus improving machine code from pop x push 5 push x jmp (==) to: push 5 jmp (==) even when (==) was no builtin primitive. A convenient (Haskellish) syntax I could come up with is: > property Commutative f where > f a b = f b a > > instance Commutative (==) > instance Commutative (+) :: Int -> Int And stating a relation between two objects: > property Isomorhism (i, j) where > i . j = id > j . i = id > > instance Isomorhism ((+x), (+(-x))) here the last line would be the abbreviated version of > instance Isomorhism (f, g) where > f x = (+x) > g x = (+(-x)) Of course in both where clauses "x" must stand for the same object. Otherwise no connection could be established between f and g. Writing down the relation in one line as an equation seems impossible to me since f has to be defined independently from g. The instance declaration simply establishes the connection. Now a more difficult example: > property NaturalTransformation n where > Functor f > Functor g > mor :: a -> b > n . (f::map) mor = (g::map) mor . n Here "(f::map) mor" stands for the the lifted morphism with respect to f. Now state that reverse is natural: > instance NaturalTransformation reverse It should be possible to infer that both functors f, g are the list functor []. Does this all make sense? Is there another mechanism that already accomplishes this? Bye, Gabor
Simon's H98 Notes
I need to think a little more about the semantic stuff, but regarding syntax I have two strong opinions. Re: Allow a type and a class to have the same name I agree with Ralf on this, and just as strongly. Maybe it is bad style to name a class the same as a type, but should the language enforce such a style? Of course not. It's always possible to write obscure programs. And besides, it is slightly bizarre for types and classes to be the only namespaces in the set of Haskell namespaces that are forced to be disjoint by mandate, rather than lexical distinctions (uppercase vs. lowercase). Re: Remove concept of "special identifier" I think all these ideas are silly: 1) to create a whole new syntactic category for "hiding" and "qualified"; 2) to swipe the identifier "hiding" from the namespace, when it is so rare to hide an imported identifier; 3) to make it easier to import an unqualified identifier than it is to import a qualified identifier, when it is the wrong thing to do 90% of the time. The convention should be reversed: by default, a module import is qualified. That eliminates the need for both "qualified" and "hiding". You can rename your identifiers explicitly, as God intended. import T = MyModule f = T.f g = T.g If MyModule has a lot of identifiers that I want to use in an unqualified way, then I have to write a lot of equations. And so be it, because... (drum roll please)... the more identifiers a module exports, the more reasons you have to qualify it! Note that this is a huge simplification, there is no loss in expressiveness, it promotes good style without bullying the user, and it encourages program scalability. As for the Prelude, well, if you ask me, it should be imported explicitly too, but imagining a hundred or so invisible equations at the top of every module is not much harder than imagining one invisible "import Prelude" there. (Maybe the thought of that is frightening enough to shock someone into muzzling that beast.) The only problem is how to hide a prelude identifier... BTW, while I'm on the soapbox, I might as well mention something else that has always bothered me (and has no hope of making it into Haskell 98), the "module" syntax. It looks like a function between namespaces, but it works in just the opposite fashion. module M(A,B,C) looks like A, B and C are arguments, but they're more like return values. Isn't this syntax more sensible?: module M (...imports...) = (...exports...) where ... for example: module Hash (module List, module T = MyModule) = (data Tbl, make, add, remove, lookup) where data Tbl = ... or even: Hash (module List, module T @ MyModule) = module (data Tbl, make, add, remove, lookup) where data Tbl = ... OK, the @ is probably taking the analogy too far but I couldn't resist... :) -- Frank A. Christoph [EMAIL PROTECTED]
Re: Fixing imports for and namespaces (was: Simon's H98 Notes)
On Mon, 19 Oct 1998, David Barton wrote: > S. Alexander Jacobson writes: >And, as long as we are supporting more ADA-like import declarations, >I would like to renew my campaign for more ADA or Java like >module namespace (packages) (yes I know, this won't be in H98) >The existing module system is: > >* too shallow for larger scale application development (because it is too > easy for different developers to create modules with the same > name). > > True, but easily fixable with the addition of a single library name. > I have never found a reason to go much further than that, as long as > the library name can be bound appropriately. I am not sure what you mean by adding a library name. My objection to the current model is that, for example with hugs, each new library requires you to add a path to your hugs path and hope that two different libraries both don't share the same module name. If module names were nested then you could reduce the liklihood of namespace collision. Java's requirement of putting the library names inside the text of modules is annoying. Use of the directory hierarchy strikes me as simpler. >* a pain when you write a package with multiple modules and each module > has to import all the other modules in the package (except itself) > > Disagree here; Haskell modules can re-export, meaning that it is easy > to create "gather nodes" that combine a bunch of modules into a > single, self-consistent, externally visible name space. A good use > for them. It may be a good use for them, but you are describing a way to implement the functionality I am describing manually. I guess it depends whether you typically use module organization within a package to support information hiding or just code organization and literate comments. Most of the time, if I think information hiding is very important, I want a different package. Java's package system has this orientation as well. All classes in the same java package can access each other. The re-export facility is nice, but I think it is more useful for establishing what functions are visible to other packages then defining what is visible within a package. >Here are the name space semantics Haskell should provide: >1. A package is a set of modules in the same directory and > a cluster is a set of clusters, packages, and modules in the same > directory > > We don't need all that mechanism. See the VHDL library / package > mechanism, for example. I am not arguing for a lot of mechanism here, just an arbitrarily deep directory tree in which to store modules (like Java, Ada, or Perl) >2. Packages and clusters should have a globally consistent name > space > > Sure; however, this can be an artifact. Binding library names to > directories with user variables works just fine. I am still not sure what you mean here. >3. Modules may import both other packages (all public declarations of all > modules in the package) or individual modules in other packages > > *shudder*. I disagree here; it is too easy for a user to change a > single name, produce name space pollution, and have no idea where it > came from. Much better to impose discipline of a single "gather > module"; i.e., one that explicitly imports and reexports the > appropriate names. > > This one has bitten me before. Really. If all import was unqualified, I'd agree with you. But there are times when it is just much more convenient to import the entirety of what is exported from another package, especially if you can import qualified. >5. Modules should have access to all functions in a package > without knowing the module in which the function sas declared > > Given by the gather modules above. True. My proposal supports multiple gather modules. (One might argue that a package should have only one public gather module, but that strikes me as overly restrictive) >6. Modules should be able to hide specific declarations from their >own package > > Explicit export? Don't we have that? No. Right now there is just a flat module namespace. So there is are no packages to protect. I am arguing for a distinction between keeping things hidden from other packages and keeping things hidden from a module's own package. Without a packaging system, this disctinction is not meaningful. I am saying that these existing export rules should stay and apply to packages. >7. Module level exports should define visibility to other packages > > I am not quite sure what you mean by this. Modules that share the same package have more access to each other's contents than they do to modules of other packages. When a module imports its own package in an unqualified manner ("package->" in my syntax), it gains access to all functions that are not declared private in all modules in the package. However, other packages don't have access to functions in a module unless those
Re: Simon's H98 Notes
Johannes Waldmann wrote: > even more, i'd like to see Ada naming convetions applied: > > you can "with" a package (import a module) (you get qualified visibility) > you can "use" a previously withe-ed package (unqualified visibility) and > you can "rename" identifiers. (that would probably be the same as "=" for > Haskell since we already got referential transparency). "with" clauses > _must_ be in the header, but "use" clauses may also be written for local > blocks (an additional plus, IMHO) I'd like to support this proposal. The 'with' and 'use' perfectly explain the intention of the import, and in my humble opinion to non-native English speakers even better than qualified vs non-qualified. Kris -- Kris Aerts - monitor MI & FVI - tel. ++32/16/32.70.74 fax. ++32/16/32.79.97 mailto:[EMAIL PROTECTED] - Web http://www.kc.kuleuven.ac.be/~kris interests: Haskell, FP and its user interfaces "Everyone is complaining about their memory, no one about their brain." La Rochefoucauld (1650)
Re: Fixing imports for and namespaces (was: Simon's H98 Notes)
S. Alexander Jacobson writes: And, as long as we are supporting more ADA-like import declarations, I would like to renew my campaign for more ADA or Java like module namespace (packages) (yes I know, this won't be in H98) The existing module system is: * too shallow for larger scale application development (because it is too easy for different developers to create modules with the same name). True, but easily fixable with the addition of a single library name. I have never found a reason to go much further than that, as long as the library name can be bound appropriately. * a pain when you write a package with multiple modules and each module has to import all the other modules in the package (except itself) Disagree here; Haskell modules can re-export, meaning that it is easy to create "gather nodes" that combine a bunch of modules into a single, self-consistent, externally visible name space. A good use for them. Here are the name space semantics Haskell should provide: 1. A package is a set of modules in the same directory and a cluster is a set of clusters, packages, and modules in the same directory We don't need all that mechanism. See the VHDL library / package mechanism, for example. 2. Packages and clusters should have a globally consistent name space Sure; however, this can be an artifact. Binding library names to directories with user variables works just fine. 3. Modules may import both other packages (all public declarations of all modules in the package) or individual modules in other packages *shudder*. I disagree here; it is too easy for a user to change a single name, produce name space pollution, and have no idea where it came from. Much better to impose discipline of a single "gather module"; i.e., one that explicitly imports and reexports the appropriate names. This one has bitten me before. Really. 4 Modules may (on a block level) import qualified or unqualified OK, I guess. 5. Modules should have access to all functions in a package without knowing the module in which the function sas declared Given by the gather modules above. 6. Modules should be able to hide specific declarations from their own package Explicit export? Don't we have that? 7. Module level exports should define visibility to other packages I am not quite sure what you mean by this. I suggest the following (strawman) implementation syntax: 1. Module/package names should have a java-like import syntax e.g. com->numeric_quest->fun_pdf (for Jan's haskell/pdf library) and map to a directory structure (off of the source/lib path) of com/numeric-quest/fun-pdf As much as I dislike getting into syntax wars, I've never found the java syntax here particularly salubrious. It is too busy, and tends to make the task of finding like names by scanning the text difficult. 2. clusters and packages as functions Generalize import. Treat clusters, packages, and modules as functions which take a name and return a cluster, package, module, or function. Since we don't want all names in all paths to pollute module name space, I suggest using the "->" operator. e.g. > myFun =\x -> com->numeric_quest->fun_pdf->somePDFFunction x Use of -> in function definitions outside or on the right of lambda expressions tells the compiler/interpreter to resolve an import. You run into a slight problem with -> polluting the type namespace, but clusters and package names are functions and are therefore lower case. > myFun::Int -> (com->numeric_quest->fun_pdf->PDFDocument) (If you want, you can interpret the type of myFun as taking an Int and the fun_pdf package and returning a PDFDocument i.e. linking to fun-pdf may happen at runtime) Import renames work like function names: > funpdf = com->numeric_quest->fun_pdf If you want to combine the current namespace with the namespace of another module or package, instead of the keyword "use", you do: > com->numeric_quest-> > myFun = \x -> fun_pdf->somePDFFunction x -- fun_pdf is inside numeric_quest > myVal = pdfConstant > fun_pdf-> -- downscope > myFun2 = \x -> anotherPDFFunction x -- anothterPDFFunction is in fun_pdf module This should feel vaguely like using lambda expressions. Is this basically an implementation suggestion? I'll leave it to Simon and othersto comment. 3. Accessing the current package with "package" To import the contents of the current package use, > package-> > myVal = somePackageFunction 3 "package" is a special keyword to denote the current package. Also applicable to the current library. 4. To hide specific declarations from the surrounding package, declare them Private e.g. Private myConst=2 (or would a private section be better?) Controls on name export control are fine here, and
Fixing imports for and namespaces (was: Simon's H98 Notes)
And, as long as we are supporting more ADA-like import declarations, I would like to renew my campaign for more ADA or Java like module namespace (packages) (yes I know, this won't be in H98) The existing module system is: * too shallow for larger scale application development (because it is too easy for different developers to create modules with the same name). * a pain when you write a package with multiple modules and each module has to import all the other modules in the package (except itself) Here are the name space semantics Haskell should provide: 1. A package is a set of modules in the same directory and a cluster is a set of clusters, packages, and modules in the same directory 2. Packages and clusters should have a globally consistent name space 3. Modules may import both other packages (all public declarations of all modules in the package) or individual modules in other packages 4 Modules may (on a block level) import qualified or unqualified 5. Modules should have access to all functions in a package without knowing the module in which the function sas declared 6. Modules should be able to hide specific declarations from their own package 7. Module level exports should define visibility to other packages I suggest the following (strawman) implementation syntax: 1. Module/package names should have a java-like import syntax e.g. com->numeric_quest->fun_pdf (for Jan's haskell/pdf library) and map to a directory structure (off of the source/lib path) of com/numeric-quest/fun-pdf 2. clusters and packages as functions Generalize import. Treat clusters, packages, and modules as functions which take a name and return a cluster, package, module, or function. Since we don't want all names in all paths to pollute module name space, I suggest using the "->" operator. e.g. > myFun =\x -> com->numeric_quest->fun_pdf->somePDFFunction x Use of -> in function definitions outside or on the right of lambda expressions tells the compiler/interpreter to resolve an import. You run into a slight problem with -> polluting the type namespace, but clusters and package names are functions and are therefore lower case. > myFun::Int -> (com->numeric_quest->fun_pdf->PDFDocument) (If you want, you can interpret the type of myFun as taking an Int and the fun_pdf package and returning a PDFDocument i.e. linking to fun-pdf may happen at runtime) Import renames work like function names: > funpdf = com->numeric_quest->fun_pdf If you want to combine the current namespace with the namespace of another module or package, instead of the keyword "use", you do: > com->numeric_quest-> > myFun = \x -> fun_pdf->somePDFFunction x -- fun_pdf is inside numeric_quest > myVal = pdfConstant > fun_pdf->-- downscope > myFun2 = \x -> anotherPDFFunction x -- anothterPDFFunction is in fun_pdf module This should feel vaguely like using lambda expressions. 3. Accessing the current package with "package" To import the contents of the current package use, > package-> > myVal = somePackageFunction 3 "package" is a special keyword to denote the current package. 4. To hide specific declarations from the surrounding package, declare them Private e.g. Private myConst=2 (or would a private section be better?) The stuff below is more speculative and assumes a modularized Haskell compiler/interpreter. 5. Future Proofing and Supporting Multiple Haskell Versions Since Haskell is changing rapidly and you don't want to force library writers to update all the time, it would be nice if the module system insulated programmers from library changes. (this is especially true with the new binary lib spec from GHC/Hugs). Since, e.g. H98, Mondrian, Polyp all evaluate to some desugared abstract haskell semantics that can be made visible to other packages, if would be nice to provide a way of telling the intepreter/compiler which "preprocessor" to apply. By convention, the first non-comment word in a module should be either "module" or the name of the interpreter e.g. > Haskell98 module moduleName (export1,export2) where > Mondrian module moduleName (export1,export2) where > Polyp module moduleName where > MySyntax module moduleName where are the first lines of different modules which tell the compiler/interpreter to use the preprocessor for Haskell98, Mondrian, Polyp, or MySyntax respectively. 6. Foreign Language Imports (even more speculative) Conversely, if you have a library with substantively different semantics e.g. Clean, OCAML, DCOM, SQL, but whose semantics can find systematic expression in the Haskell type/name system, then you might have semantic importers of the form > haskellGraphics = java2Haskell "java.lang.awt" or > mySchema = schemaSQL2Haskell mySQLSchema The first imports java graphics for use in Haskell. The second takes a sql schema and generates corresponding Haskell datatypes and functions. haskellAWT and mySchema have type Package and
Re: Simon's H98 Notes
Frank Christoph writes: > The convention should be reversed: by default, a module import is qualified. > That eliminates the need for both "qualified" and "hiding". You can rename > your identifiers explicitly, as God intended. are we talking Haskell98 here? anyway, i'd like to second that proposal. even more, i'd like to see Ada naming convetions applied: you can "with" a package (import a module) (you get qualified visibility) you can "use" a previously withe-ed package (unqualified visibility) and you can "rename" identifiers. (that would probably be the same as "=" for Haskell since we already got referential transparency). "with" clauses _must_ be in the header, but "use" clauses may also be written for local blocks (an additional plus, IMHO) -- Dr. Johannes Waldmann Institut fur InformatikUniversitat Leipzig [EMAIL PROTECTED] http://www.informatik.uni-leipzig.de/~joe/ Augustusplatz, D-04109 Leipzig, Germany, Tel/Fax (+49) 341 97 32 204/209
Haskell 98 - The Underbar
Ralf Hinze wrote: > >* make '_' lexically a valid identifier character anywhere >* but disallow identifiers starting with '_' > > Thus '___' would lex as '___' but then be rejected. '_' on its own remains a > wild-card pattern, and illegal in expressions. > > > ] `_' is a special case whatever option one chooses. So I can see no real > ] advantage in disallowing identifiers starting with '_'. IMHO the simplest rule would be to allow '_' anywhere a lowercase letter is allowed. And "_" becomes just an ordinary keyword. Cheers, - Andreas
Re: scientific computing
On Sat, 17 Oct 1998, S.D.Mechveliani wrote: > Only the meaning of the words `scientific computing' in programming > has 90% changed since 1960-1970. > Now it means mainly the *symbolic* (not approximate) computation that > the scientists and engineers usually do on the paper. I think that the terms `scientific computing' were being used in the sense of `computing in order to acheive scientific goals' rather than any other more technical meaning. My experience is again rather limited but I've hung around one maths dept & two computer science departments and I'd say that _at most_ 60% of people who have been computing have been doing symbolic work only, at a conservative estimate. Most people these days do some symbolic algebra but rarely at the sort of depth which requires things beyond standard packages for Maple or Mathematica. > The `number crunching engine' for the tasks like the large float matrix > inversion constitutes maybe 5% of the scientific computing matter > (still, it is important). There's lots of numerically intensive algorithms out there which aren't simple applications of classical methods. > So testing the fitness for the scientific computing will rather mean > to program, say, the polynomial factorization in Haskell, or maybe, the > logical resolution method, and compare its performance to AXIOM, Maple, > MuPAD ones. This is definitely one area in which usefulness for scientific computing should be tested, but it's by no means the only one. Maybe we should try and get an informal poll (on this list) of the sorts of areas in which haskell is currently, or might in the future, be used to discover other areas of scientific computing to consider. ___cheers,_dave__ email: [EMAIL PROTECTED]I _never_ buy items advertised by those www.cs.bris.ac.uk/~tweed/pi.htm annoying cards that drop from magazines work tel: (0117) 954-5253 or by bulk e-mail on principle.