Re: topdelcs / decls
On Fri, 23 Oct 1998, Ralf Hinze wrote: | If local instance declarations were admissable I could possibly write | ... lots of hand-waving ... | | sortBy (rel :: Rel a) = sort where instance Ord a where (=) = rel Look at Mondrian: http://www.cs.chalmers.se/~koen/Papers/mondrian.ps The intention there was that this would be easy to do. Dictonaries are implemented by records (possibly containing polymorphic functions): class Ord a where { (=) :: a - a - Bool } defines a record type containing one field: =. If we want to compare two elements, we can explicitly choose a Ord-record: intOrd :: Ord Int intOrd = Ord{ (=) = primIntCompare } 1 intOrd.= 2 :: Bool Or we can leave it implicit: 1 = 2 :: Ord Int = Bool Note that the type expresses that we haven't specified an ordering yet. Implementing a sorting function, is like adding an extra selector function to the Ord record. It goes like this: sort :: Ord a = [a] - [a] sort xs = ... = ... xs ... Now, if we want to use sort on different orderings: sort [1,2,3,4] :: Ord Int = [Int] intOrd.sort [1,2,3,4] :: [Int] crazyOrd.sort [1,2,3,4] :: [Int] ... We can also implement a function that flips a sorting: rev :: Ord a - Ord a rev ord = Ord{ (=) = flip (ord.=) } Note that this is defined as a record transformer, rather than as a new selector function for Ord. And now we can define "revsort", using the flipped ordering: revsort :: Ord a = [a] - [a] ord.revsort = (rev ord).sort I really like these ideas, and the paper has a few more examples. Unfortunately there seem to be some semantic issues wrong with it (what to do if you have multiple record in your contexts). Regards, Koen. -- Koen Claessen, [EMAIL PROTECTED], http://www.cs.chalmers.se/~koen, Chalmers University of Technology.
Re: topdelcs / decls
Hello! On Fri, Oct 23, 1998 at 01:44:58PM +0200, Johannes Waldmann wrote: Your thought would destroy equational reasoning! For example you would be able to define different equalties on the same data structure. So Red==Black could be False in one place and True in another place. Does that make any sense? well, yes and no, of course :-) for instance, i could want to sort a list, according to two different criteria, using two different instances of Ord. newtype IntFunnilyOrdered = IFO Int instance Ord IntFunnilyOrdered where compare (IFO x) (IFO y) | even x even y = compare x y | even x odd y = LT | odd x even y = GT | otherwise= compare x y int_from_ifo (IFO x) = x newtype IntReverse = IR Int instance Ord IntReverse where compare (IR x) (IR y) = compare y x int_from_ir (IR x) = x Now, you can do map int_from_ir $ sort $ map IR l or map int_from_ifo $ sort $ map IFO l Ideally, the compiler should figure out that map IFO and map int_from_ifo are essentially noops, except changing the class instances to use. Or use a function sortWith :: (a - a - Ordering) - [a] - [a] and give it the ordering to use as parameter. moreover, i would need these instances only while sorting, so i would like to keep them local. If you use the instances once, I think using something like sortWith instead will be more elegant. [...] i fear there are more problems hidden. let's take this: data T = ... xx = let instance Ord T where ... x :: T = ... in x yy = let instance Ord T where ... y :: T = ... in y do xx and yy have the same type? yes and no, again, it looks like they belong to different (incomparable) subtypes of T. what about the expression (xx yy)? which instance to use? none - on the outside it's not visible that T is any Ord instance, so you cannot compare them at all. Hmmm. So in your sorting example: sort :: Ord a = [a] - [a] sort ... = ... ..., foo = let instance Ord T where compare ... = ... in sort (something::[T]) There's no Ord instance visible in the definition of sort. And if you dynamically assign those instances and transport them to sort, this becomes a real mind twist: sort :: ... (as above) somelist :: [T] somelist = let instance Ord T where ... in (generate some list of values in T) sortedlist :: [T] sortedlist = let instance Ord T where [different from the above instance] in sort somelist Now, which instance to usw? That bound to the values when they were generated, i.e. that local to somelist? Or is that instance replaced by that in sortedlist by that let instance binding? That somehow twists my mind :-) Regards, Felix.
Re: Fixing imports for and namespaces (was: Simon's H98 Notes)
Fergus Henderson writes: No, different uids don't work fine in the multiprogrammer case. The programmer that is compiling the source code needs read access to all of it (for using tools like `grep', if nothing else). Once he has that read access, nothing prevents him from violating the encapsulation. Let's see here --- you want him to be able to do reads like grep but not refer to the units directly? You ask too much of *any* mechanism (unless you restrict operations like grep and others, doing special versions, in which case they can do the appropriate superuser stuff). Either you can trust the programmer to follow conventions, or you restrict any kind of read access; without that restriction, he or shee can always make a local copy and do what he or she wills. But even *if* you decide that some more sophisticated mechanism of version control is necessary, it is properly an operating system function, *not* a language function. If you decide that a "grep" is OK, but compile access is not, there is no reason whatever to decide that compilation is your only "forbidden" function. It makes a lot more sense to add an operating system function --- say, granting access by tool rather than by specific user or group ID --- that gets you the finer grained access control you need. Then you only implement it once. Under your suggestion, it not only gets implemented by multiple tools, but it gets codified in the entry format (whether a computer language or a document control system) of multiple tools, each in a different way. Chaos! It all boils down to: access control to files is the responsibility of the operating system, *not* a programming language. The most a language should do is make responsible conventions possible and expressible, and Haskell can do that with a very limited extension. 2) The compiler can (and should) be intelligent enough to detect the importation of symbols only through non-functional (gather) modules. This is not a big test to perform. So the compiler should enforce this convention? No; detect it and take advantage of it. Most of the below is variations on a theme, which make lots of sense if you accept the basic assumption that enforcing access control conventions is properly a function of the language feature; under that assumption, I agree with most of it. So: snip I don't see how that helps. Every programmer on the team may need to modify any file (in order to fix a bug, for example). So all programmers need write access to every file. This does not correspond to any configuration controlled project that I have ever worked on, so I am at sea. In my world, if you need a file that is outside your own package, you need to go to the configuration manager (who may or may not be the project manager) for permission to check out the file to make the change. This may be as simple as an Email, or it may even require review. Allowing the programmer to just do it, on his own hook, is well outside any kind of configuration control guidelines I have ever worked under. This may be a commercial / university kind of thing. I know of no company that would work with these kinds of guidelines, which may account for our different approach to this whole question. Well, normally I check out all the modules in the system. With CVS, I type out `cvs checkout mercury' and it checks out all the modules in the entire system, giving me both read and write access to all of them. Then I type `make' and it compiles everything. This is nice and simple, and it works. We work in very different environments! Yes, you may be right. But I don't think a language should require the use of a particular configuration management style. And therefore I'm not keen on any solution which relies on the configuration management style rather than the language to enforce encapsulation. And, again IMHO, it is the task of the language to *define* the encapsuation (or to allow that encapsulation to be defined), and the job of the operating system or programming environment to enforce it (or to trust to convention, depending). And still IMHO, Haskell can do this definition with very little change. Dave Barton * [EMAIL PROTECTED] )0( http://www.averstar.com/~dlb
Re: Functional DSP
Philip Wadler wrote: By the way, FFTW although written in C, was generated by a functional program written in Caml. You can find more details on the web page I asked the authors (Steven Johnson and Matteo Frigo from MIT) a few months ago why they chose Objective Caml over SML, Haskell, and Scheme. The answer was bascially because they knew it already and it ran well on one of their older laptops. I think what it more interesting is that fact that the code uses explicit recursion (as oppose to "traditional" loop based algorithms) and all of the codelets/butterflys are executed via byte code. On top of that, it managed to beat most other FFT packages available today. --Matt Donadio ([EMAIL PROTECTED])
Re: Functional DSP
On Sat, 24 Oct 1998, Philip Wadler wrote: I was planning to try similar things you have mentioned on your page, such as interfacing to "the fastest FFT in the West" (FFTW) via GreenCard, ... By the way, FFTW although written in C, was generated by a functional program written in Caml. You can find more details on the web page Functional Programming in the Real World http://www.cs.bell-labs.com/~wadler/realword/ Yes, I know it, but thank you for pointing it out. It is amazing to see how useful caml/ocaml is in development of other goodies, such as Pict, Joint Calculus, Ensemble, etc. I think that they did a good job with interfacing it to C in a variety of ways: toplevel, bytecode, native code, embedded bytecode, etc.; and that's probably one of the answers why it is so popular - at least among researchers. Jan -- P
Re: Haskell 98
Simon Peyton-Jones [EMAIL PROTECTED] writes: Consider the function t :: T a = T a - T a I think that it's far from clear what each of the T's mean! Worse, in Haskell 2 we'll also have t :: T T = T a - T a In (T T) one is class and the other is a type constructor. I'm not convinced by the argument "this allows you to write obfuscated Haskell". After all, Haskell is already a wonderful language for writing obfuscated code; eg. what does the following definition mean f f = f is it a static error (re-use of 'f'), a type error, or a definition of the identity function? (it's the latter). Here's to cleaning up the language, and to more exciting obfuscated Haskell competitions! Cheers, Simon -- Simon Marlow [EMAIL PROTECTED] University of Glasgow http://www.dcs.gla.ac.uk/~simonm/ finger for PGP public key
Re: Functional DSP
I was planning to try similar things you have mentioned on your page, such as interfacing to "the fastest FFT in the West" (FFTW) via GreenCard, ... By the way, FFTW although written in C, was generated by a functional program written in Caml. You can find more details on the web page Functional Programming in the Real World http://www.cs.bell-labs.com/~wadler/realword/ -- P