From maldim@gmx.net Sat, 04 Jan 2003 10:30:05 +0200 Date: Sat, 04 Jan 2003 10:30:05 +0200 From: Dmitry Malenko maldim@gmx.net Subject: [clean-list] Pattern matching Hi! I'm new to Clean, so forgive if it is a silly question. I have the following code: module test import StdEnv s x = 3*x s [x] = 2*x s [x,y] = x*y Start = s 4 When compile it I get warning: "[test.icl,5,s] alternative will never match". Nevertheless program runs perfectly and gives expected result 12. Start = s [4] will give type error that Int can not be unified with [v1], so s seems to have type s :: Int -> Int. But what about definitions with list as a parameter? Why there is no complains? Again, warning seems to be incorrect. How s in the example above is typed? BTW How can I make "Types" window appear in Clean IDE? -- Best regards, Dmitry Malenko. +----------------------------------------------------+ Registered Linux user #258004 ALT Linux Team http://www.altlinux.ru Titano project http://titano.sourceforge.net +----------------------------------------------------+ Do you guys know what you're doing, or are you just hacking? From dvanarkel@mac.com Sat, 4 Jan 2003 18:05:46 +0100 Date: Sat, 4 Jan 2003 18:05:46 +0100 From: Diederik van Arkel dvanarkel@mac.com Subject: [clean-list] Pattern matching On Saturday, January 4, 2003, at 09:30 AM, Dmitry Malenko wrote: > Hi! > > I'm new to Clean, so forgive if it is a silly question. > > I have the following code: > > module test > > import StdEnv > > s x = 3*x > s [x] = 2*x > s [x,y] = x*y > > Start = s 4 > > When compile it I get warning: "[test.icl,5,s] alternative will never > match". Nevertheless program runs perfectly and gives expected result > 12. > What's happening here is that apparently the compiler throws away the second and third alternatives for s because the first alternative wil always succeed. It does this before typechecking and therefore does not notice that the types of these alternatives are inconsistent. > Start = s [4] > will give type error that Int can not be unified with [v1], so s seems > to have type s :: Int -> Int. But what about definitions with list as > a parameter? Why there is no complains? > Indeed s has type Int -> Int. See above for the explanation of why there is no error on the type of the second and third alternatives. You seem to want s to have both type Int -> Int and [Int] -> [Int], you might want to look up type classes in the reference manual for a possible solution to what you are trying to achieve. If this is not what you are looking for you may want to post a message stating your requirements more precisely. > Again, warning seems to be incorrect. > > How s in the example above is typed? > > BTW How can I make "Types" window appear in Clean IDE? > You want to modify the setting under the menu Module:Module Options:List Types, if you set this to 'All Types' you should get the 'Types' window. Regards, Diederik van Arkel diederik@cs.kun.nl P.S. There was no need to send your news message twice, the clean-list is a moderated list and it can occasionally take some time before your mail is transmitted to the list. From fjh@cs.mu.OZ.AU Mon, 6 Jan 2003 03:37:45 +1100 Date: Mon, 6 Jan 2003 03:37:45 +1100 From: Fergus Henderson fjh@cs.mu.OZ.AU Subject: [clean-list] Pattern matching On 04-Jan-2003, Diederik van Arkel wrote: > > On Saturday, January 4, 2003, at 09:30 AM, Dmitry Malenko wrote: > > >s x = 3*x > >s [x] = 2*x > >s [x,y] = x*y > > > >Start = s 4 > > > >When compile it I get warning: "[test.icl,5,s] alternative will never > >match". Nevertheless program runs perfectly and gives expected result > >12. > > What's happening here is that apparently the compiler throws away the > second and > third alternatives for s because the first alternative wil always > succeed. It does > this before typechecking and therefore does not notice that the types > of these > alternatives are inconsistent. Presumably this behaviour is a (minor) bug in the Clean compiler... it ought to do type checking before applying such optimizations, right? -- Fergus Henderson | "I have always known that the pursuit The University of Melbourne | of excellence is a lethal habit" WWW: | -- the last words of T. S. Garp. From dvanarkel@mac.com Sun, 5 Jan 2003 18:13:11 +0100 Date: Sun, 5 Jan 2003 18:13:11 +0100 From: Diederik van Arkel dvanarkel@mac.com Subject: [clean-list] Pattern matching On Sunday, January 5, 2003, at 05:37 PM, Fergus Henderson wrote: > On 04-Jan-2003, Diederik van Arkel wrote: >> >> On Saturday, January 4, 2003, at 09:30 AM, Dmitry Malenko wrote: >> >>> s x = 3*x >>> s [x] = 2*x >>> s [x,y] = x*y >>> >>> Start = s 4 >>> >>> When compile it I get warning: "[test.icl,5,s] alternative will never >>> match". Nevertheless program runs perfectly and gives expected result >>> 12. >> >> What's happening here is that apparently the compiler throws away the >> second and >> third alternatives for s because the first alternative wil always >> succeed. It does >> this before typechecking and therefore does not notice that the types >> of these >> alternatives are inconsistent. > > Presumably this behaviour is a (minor) bug in the Clean compiler... > it ought to do type checking before applying such optimizations, right? > Presumably yes, hence the cc to the bug reporting address (clean@...). Regards, Diederik van Arkel From c.wartena@linguatec-es.de Fri, 17 Jan 2003 16:02:13 +0100 Date: Fri, 17 Jan 2003 16:02:13 +0100 From: c.wartena@linguatec-es.de c.wartena@linguatec-es.de Subject: [clean-list] MySQL Dear Clean-Experts, can anyone tell me where I can get information how to access a MySQL Database fron clean? Thanks Christian -- Dr. Christian Wartena Linguatec Entwicklung & Services Hebelstraße 14 D-69115 Heidelberg Tel. 06221 - 905 60 04 Fax 06221-182992 http://www.linguatec-es.de ************************************************************* Neu: Kostenlose Wörterbücher für den Personal Translator http://www.linguatec-es.de/Deutsch/Interaktiv/bwb-tauschboerse.htm ************************************************************* From bvgastel@bitpowder.com Sat, 18 Jan 2003 02:32:07 +0100 Date: Sat, 18 Jan 2003 02:32:07 +0100 From: Bernard van Gastel bvgastel@bitpowder.com Subject: [clean-list] MySQL Hi Christian, My guess is that there is no MySQL interface for Clean. The MySQL C api is nice (actually I know the PostgreSQL interface, and looked briefly at the MySQL interface. The general structure seemed the same), so it should not be too hard to make a Clean library for MySQL. Bernard c.wartena@linguatec-es.de heeft op vrijdag 17 januari 2003 om 16:02 het volgende geschreven: > Dear Clean-Experts, > > can anyone tell me where I can get information how to access a > MySQL Database fron clean? > > Thanks > > Christian > > -- Dr. Christian Wartena > Linguatec Entwicklung & Services > Hebelstraße 14 > D-69115 Heidelberg > Tel. 06221 - 905 60 04 > Fax 06221-182992 > http://www.linguatec-es.de > > ************************************************************* > Neu: Kostenlose Wörterbücher für den Personal Translator > http://www.linguatec-es.de/Deutsch/Interaktiv/bwb-tauschboerse.htm > ************************************************************* > > > > > _______________________________________________ > clean-list mailing list > clean-list@cs.kun.nl > http://www.cs.kun.nl/mailman/listinfo/clean-list From maldim@gmx.net Sat, 18 Jan 2003 14:20:46 +0200 Date: Sat, 18 Jan 2003 14:20:46 +0200 From: Dmitry Malenko maldim@gmx.net Subject: [clean-list] Sparkle manual Hi, All! Is there any manual on using Sparkle besides "Theorem proving for functional programmers" paper avaliable? What is the syntax used for entering new thorems? BTW What is current status of Sparkle? Is there any ongoing development? Last 0.0.3a from Jan 2002 seems a bit outdated. -- Best regards, Dmitry Malenko. +----------------------------------------------------+ Registered Linux user #258004 ALT Linux Team http://www.altlinux.ru Titano project http://titano.sourceforge.net +----------------------------------------------------+ U X e dUdX, e dX, cosine, secant, tangent, sine, 3.14159... From maartenm@cs.kun.nl Mon, 20 Jan 2003 10:55:27 +0100 Date: Mon, 20 Jan 2003 10:55:27 +0100 From: Maarten de Mol maartenm@cs.kun.nl Subject: [clean-list] Sparkle manual Hello Dmitry, > Hi, All! > > Is there any manual on using Sparkle besides "Theorem proving for > functional programmers" paper avaliable? What is the syntax used for > entering new thorems? Unfortunately, there is no manual for Sparkle available. The only other very limited source of information is the website at http:\\www.cs.kun.nl\Sparkle. The syntax for entering new theorems is as follows: ----------------------------------------------------- EQUALITY: "E = E" NEGATION: "~P" CONJUNCTION: "P /\ Q" DISJUNCTION: "P \/ Q" IMPLICATION: "P -> Q" or "P => Q" EQUIVALENCE: "P <-> Q" or "P <=> Q" UNIVERSAL QUANTIFICATION: "[x::T] P" EXISTENTIAL QUANTIFICATION:"{x::T} P" ----------------------------------------------------- Notes: * The types in the quantifications may be omitted. (Sparkle tries to derive types for variables automatically, but this might fail in some case, such as overloading). * Universal quantifications may be omitted completed. (Sparkle automatically adds universal quantifications for all free variables it finds) > BTW What is current status of Sparkle? Is there any ongoing development? > Last 0.0.3a from Jan 2002 seems a bit outdated. Development on Sparkle has effectively been frozen since January 2002, when I started tackling remaining theoretical issues and started writing my PhD-thesis. Hopefully, when funding can be arranged, work on Sparkle can be continued this summer. > Best regards, > Dmitry Malenko. Greetings, Maarten de Mol From EZuurbier@Abz.nl Tue, 21 Jan 2003 11:28:35 +0100 Date: Tue, 21 Jan 2003 11:28:35 +0100 From: Erik Zuurbier EZuurbier@Abz.nl Subject: [clean-list] Sparkle and ABC-code This message is in MIME format. Since your mail reader does not understand this format, some or all of this message may not be legible. ------_=_NextPart_001_01C2C137.DAD6AFA0 Content-Type: text/plain Maarten de Mol wrote: Unfortunately, there is no manual for Sparkle available. In that case I will just ask: Sparkle is able to convert full Clean code to desugared Clean. The Sparkle website only excludes I/O-code. Does that mean that proofs *can* be generated and checked for functions that include ABC-code? After all ABC-code, included in "code {...}" *is* part of the official Clean syntax, right? Regards Erik Zuurbier (On the other hand, if you view ABC-code as an official part of the Clean language, Clean's claim to be 'pure' seems to be unjustified.) ------_=_NextPart_001_01C2C137.DAD6AFA0 Content-Type: text/html Content-Transfer-Encoding: quoted-printable Sparkle and ABC-code

Maarten de Mol wrote:
Unfortunately, there is no manual = for Sparkle available.

In that case I will just ask: Sparkle = is able to convert full Clean code to desugared Clean. The Sparkle = website only excludes I/O-code. Does that mean that proofs *can* be = generated and checked for functions that include ABC-code? After all = ABC-code, included in "code {...}" *is* part of the official = Clean syntax, right?

Regards Erik Zuurbier

(On the other hand, if you view = ABC-code as an official part of the Clean language, Clean's claim to be = 'pure' seems to be unjustified.)

------_=_NextPart_001_01C2C137.DAD6AFA0-- From maartenm@cs.kun.nl Tue, 21 Jan 2003 12:01:09 +0100 Date: Tue, 21 Jan 2003 12:01:09 +0100 From: Maarten de Mol maartenm@cs.kun.nl Subject: [clean-list] Sparkle and ABC-code > Maarten de Mol wrote: > Unfortunately, there is no manual for Sparkle available. > > In that case I will just ask: Sparkle is able to convert full Clean code to > desugared Clean. The Sparkle website only excludes I/O-code. Does that mean > that proofs *can* be generated and checked for functions that include > ABC-code? After all ABC-code, included in "code {...}" *is* part of the > official Clean syntax, right? It is part of the Clean syntax. But I don't think it is also part of the Clean *semantics*. How SPARKLE handles ABC-code: It doesn't. Instead, it recognizes special functions from the standard environment (currently by looking at the combination (name,module)) and assigns a predefined meaning to these. All functions written in ABC-code in the standard environment are recognized this way. Other functions written in ABC-code will not be recognized and cannot be compiled by SPARKLE. By the way: there is room for improvement here, because we do have an ABC-interpreter available. Assigning a proper semantics should be possible for a subset of ABC-code. > Regards Erik Zuurbier > > (On the other hand, if you view ABC-code as an official part of the Clean > language, Clean's claim to be 'pure' seems to be unjustified.) Greetings, Maarten de Mol From f.todescato@larisys.fr Wed, 22 Jan 2003 16:20:22 +0100 Date: Wed, 22 Jan 2003 16:20:22 +0100 From: Fabien Todescato f.todescato@larisys.fr Subject: [clean-list] True Uniqueness Typing Error or Compiler Bug ? Dear Cleaners, I get the following uniqueness typing error from the 2.0.2 compiler : Type error [uTypeBug.icl,14,nextSymbol] : specified type ( Char -> Int -> u:File -> u:File) (u:File->u:File) Int u:File -> u:File conflicts with derived type ( Char -> Int -> * File -> * File) (* File->* File) Int * File -> * File which I find quite confusing since the former type can be unified with the latter with the substitution u = '*'. This arises when trying to compile the following code snippet : module uTypeBug import StdEnv class nextSymbol context thread symbol :: ( symbol context .thread -> .thread ) ( .thread -> .thread ) context .thread -> .thread instance nextSymbol Int File Char where nextSymbol yes no index file # (ok,file) = fseek file index FSeekSet | not ok = no file # (ok,char,file) = freadc file | not ok = no file # index = index + 1 = yes char index file Start = "uTypeBug" Any clue ? Best regards, Fabien Todescato PS.Happy new year to you all, and kudos to the Clean Team for bringing to us a lot of improvement to an already great system. From EZuurbier@Abz.nl Thu, 23 Jan 2003 10:35:37 +0100 Date: Thu, 23 Jan 2003 10:35:37 +0100 From: Erik Zuurbier EZuurbier@Abz.nl Subject: [clean-list] True Uniqueness Typing Error or Compiler Bug ? This message is in MIME format. Since your mail reader does not understand this format, some or all of this message may not be legible. ------_=_NextPart_001_01C2C2C2.C91A8E80 Content-Type: text/plain Fabien wrote: >Dear Cleaners, I get the following uniqueness typing error from the 2.0.2 compiler : >Type error [uTypeBug.icl,14,nextSymbol] : specified type >( Char -> Int -> u:File -> u:File) (u:File->u:File) Int u:File -> u:File conflicts with derived type >( Char -> Int -> * File -> * File) (* File->* File) Int * File -> * File >which I find quite confusing since the former type can be unified with the latter with the substitution u = '*'. My understanding of uniqueness attributes such as u: is that each variable can take on two different values, unique or non-unique. That would mean that your specified type asserts that the function has two different type instantiations: ( Char -> Int -> * File -> * File) (* File->* File) Int * File -> * File this is is the one derived by the compiler, and: ( Char -> Int -> File -> File) ( File-> File) Int File -> File The type checker apparently cannot agree with this latter one. And indeed the function's implementation contains fseek and freadc - operations that work only on unique files. Regards Erik Zuurbier ------_=_NextPart_001_01C2C2C2.C91A8E80 Content-Type: text/html Content-Transfer-Encoding: quoted-printable True Uniqueness Typing Error or Compiler Bug ?

Fabien wrote:
>Dear Cleaners, I get the = following uniqueness typing error from the 2.0.2 compiler :
>Type error = [uTypeBug.icl,14,nextSymbol] : specified type
>( Char -> Int -> u:File = -> u:File) (u:File->u:File) Int u:File -> u:File conflicts = with derived type
>( Char -> Int -> * File = -> * File) (* File->* File) Int * File -> * File
>which I find quite confusing = since the former type can be unified with the latter with the = substitution u =3D '*'.


My understanding of uniqueness = attributes such as u: is that each variable can take on two different = values, unique or non-unique. That would mean that your specified type = asserts that the function has two different type = instantiations:

( Char -> Int -> * File -> * = File) (* File->* File) Int * File -> * File

this is is the one derived by the = compiler, and:

( Char -> Int ->   = File ->   File) (  File->  File) = Int   File ->   File

The type checker apparently cannot = agree with this latter one. And indeed the function's implementation = contains fseek and freadc - operations that work only on unique = files.

Regards Erik Zuurbier=20

------_=_NextPart_001_01C2C2C2.C91A8E80-- From f.todescato@larisys.fr Thu, 23 Jan 2003 10:59:28 +0100 Date: Thu, 23 Jan 2003 10:59:28 +0100 From: Fabien Todescato f.todescato@larisys.fr Subject: [clean-list] RE: True Uniqueness Typing Error or Compiler Bug ? Thank you Erik for these enlightening comments, Your explanation makes sense but I have trouble making it fit with my current understanding of uniqueness variable and type-checking. Usually, type variables introduce degrees of freedom, so that for example x -> x is less restrictive than Int -> Int, and this agrees with the usual partial order on type terms. That is, x -> x is more general than Int -> Int because there exists a substitution s such that s(x->x) = Int->Int, namely s = { x = Int }. Now, from your explanation it is somehow the reverse with uniqueness attributes. Indeed, though u:Int -> u:Int = * Int -> * Int with the substitution u = *, actually the type u:Int -> u:Int is more restrictive since it requires that both unique and non-unique Int may be manipulated by the function so typed. There is a general pattern at work here : uniqueness attributes actually put constraints on the types, therefore, the more freedom in the constraints on the type, the less freedom on the type. I will have to go through the reference manual again to get rid of my misconceptions about uniqueness typing, I fear. Again, thank you for your comments. Best regards, Fabien Todescato > -----Message d'origine----- > De: Erik Zuurbier [SMTP:EZuurbier@Abz.nl] > Date: jeudi 23 janvier 2003 10:36 > À: 'clean-list@cs.kun.nl' > Cc: 'f.todescato@larisys.fr' > Objet: True Uniqueness Typing Error or Compiler Bug ? > > Fabien wrote: > >Dear Cleaners, I get the following uniqueness typing error from the 2.0.2 > compiler : > >Type error [uTypeBug.icl,14,nextSymbol] : specified type > >( Char -> Int -> u:File -> u:File) (u:File->u:File) Int u:File -> u:File > conflicts with derived type > >( Char -> Int -> * File -> * File) (* File->* File) Int * File -> * File > >which I find quite confusing since the former type can be unified with > the latter with the substitution u = '*'. > > > My understanding of uniqueness attributes such as u: is that each variable > can take on two different values, unique or non-unique. That would mean > that your specified type asserts that the function has two different type > instantiations: > > ( Char -> Int -> * File -> * File) (* File->* File) Int * File -> * File > > this is is the one derived by the compiler, and: > > ( Char -> Int -> File -> File) ( File-> File) Int File -> File > > The type checker apparently cannot agree with this latter one. And indeed > the function's implementation contains fseek and freadc - operations that > work only on unique files. > > Regards Erik Zuurbier > From f.todescato@larisys.fr Thu, 23 Jan 2003 11:41:51 +0100 Date: Thu, 23 Jan 2003 11:41:51 +0100 From: Fabien Todescato f.todescato@larisys.fr Subject: [clean-list] About semantic restrictions on type classes. Dear Cleaners, In §6.11 of the Clean Language Report 2.1, it is said that : A type instance of an overloaded type must be a flat type , i.e. a type of the form T a1...an where ai are type variables which are all different. supposing I have the following : class k x y :: x y -> y The above-mentionned restriction prevents the definition of : instance k x ( t x ) where t is some type constructor. Now, if the class k is instead defined as follows : class k x t y :: x ( t y ) -> t y I can write : instance k x t y. That is, using type-constructor classes may provide in some cases a workaround to the limitations imposed by the 'flat type' semantic restriction above. Now, there is certainly a good reason why that 'flat type' semantic restriction does exist, a reason however that is currently beyond my reach. Could anybody give a few explanations about that restriction ? Sincerely yours, Fabien Todescato From f.todescato@larisys.fr Thu, 23 Jan 2003 12:26:46 +0100 Date: Thu, 23 Jan 2003 12:26:46 +0100 From: Fabien Todescato f.todescato@larisys.fr Subject: [clean-list] RE: True Uniqueness Typing Error or Compiler Bug ? Sjakk Smetsers writes : No, it's more or less the same. ... I don't understand what you are trying to say here. But the error in your original example has nothing to do with peculiarities in the uniqueness typing system: you have specified a type which is more general than the type derived by the compiler. This is also not allowed with standard types. It is actually the same as typing a function with type Int -> Int as a -> a and saying that the specified type correct since you can substitute Int for a. My goodness ! You're absolutely right. I confused the type prescribed by the type class with the the type derived by the compiler, and vice-versa ! Thank you for settling the matter down and clearing my head :) Best regards, Fabien Todescato > -----Message d'origine----- > De: Sjaak Smetsers [SMTP:sjakie@cs.kun.nl] > Date: jeudi 23 janvier 2003 11:54 > À: Fabien Todescato > Objet: Re: [clean-list] RE: True Uniqueness Typing Error or > Compiler Bug ? > > Hi Fabian > > >Your explanation makes sense but I have trouble making it fit with my > >current understanding of uniqueness variable and type-checking. > > > >Usually, type variables introduce degrees of freedom, so that for example > x > >-> x is less restrictive than Int -> Int, and this agrees with the usual > >partial order on type terms. That is, x -> x is more general than Int -> > Int > >because there exists a substitution s such that s(x->x) = Int->Int, > namely s > >= { x = Int }. > > > >Now, from your explanation it is somehow the reverse with uniqueness > >attributes. > > No, it's more or less the same. > > >Indeed, though u:Int -> u:Int = * Int -> * Int with the > >substitution u = *, actually the type u:Int -> u:Int is more restrictive > >since it requires that both unique and non-unique Int may be manipulated > by > >the function so typed. > > u:Int -> u:Int is less restrictive than *Int -> *Int since it can be > applied to an Int-object as well as to *Int-object whereas the latter one > can only be applied to a *Int-object. > > >There is a general pattern at work here : uniqueness attributes actually > put > >constraints on the types, therefore, the more freedom in the constraints > on > >the type, the less freedom on the type. > > > I don't understand what you are trying to say here. But the error in your > original example has nothing to do with peculiarities in the uniqueness > typing system: you have specified a type which is more general than the > type derived by the compiler. This is also not allowed with standard > types. > It is actually the same as typing a function with type Int -> Int as a -> > a > and saying that the specified type correct since you can substitute Int > for a. > > > >I will have to go through the reference manual again to get rid of my > >misconceptions about uniqueness typing, I fear. > > > >Again, thank you for your comments. > > > >Best regards, Fabien Todescato > Regards, > > Sjaak Smetsers From sjakie@cs.kun.nl Thu, 23 Jan 2003 12:41:10 +0100 Date: Thu, 23 Jan 2003 12:41:10 +0100 From: Sjaak Smetsers sjakie@cs.kun.nl Subject: [clean-list] About semantic restrictions on type classes. Dear Fabian, >In §6.11 of the Clean Language Report 2.1, it is said that : > > A type instance of an overloaded type must be a flat type , i.e. a >type of the form T a1...an where ai are type variables which are all >different. In Clean we have the same restriction on instance types as in Haskell. I don't know whether this restriction is fundamental, what i do know is that the current implementation of Clean cannot be extended (easily) in such a way that it can deal with 'overlapping' instance types. >supposing I have the following : > >class k x y :: x y -> y > >The above-mentionned restriction prevents the definition of : > >instance k x ( t x ) > >where t is some type constructor. > >Now, if the class k is instead defined as follows : > >class k x t y :: x ( t y ) -> t y > >I can write : > >instance k x t y. So what? In the first case your (illegal) instance would have type x ( t x ) -> ( t x ) whereas in the second case it has type x ( t y ) -> t y Two different instances, so what are you trying to illustrate? >That is, using type-constructor classes may provide in some cases a >workaround to the limitations imposed by the 'flat type' semantic >restriction above. I don't see your point. Regards, Sjaak Smetsers From f.todescato@larisys.fr Thu, 23 Jan 2003 13:30:21 +0100 Date: Thu, 23 Jan 2003 13:30:21 +0100 From: Fabien Todescato f.todescato@larisys.fr Subject: [clean-list] About semantic restrictions on type classes. Sjaak Smetsers writes : So what? Huh, sorry, I meant the 2nd case to be : class k x t :: x ( t x ) -> t x so that the instance : instance k x t has type x ( t x ) -> t x, a type that the 1st case class : class k x y :: x y -> y cannot be instanciated to because of the type flat semantic restriction. That is : class k x y :: x y -> y instance k x ( t x ) is illegal, as you emphasized. I don't see your point. Well, I was designing for some concrete programming task a type class and encountered the flat type restriction that would prevent me for instanciating my type class as I wanted. After some head-scratching I realized that I could have the right class instance provided I changed the class definition and used a type constructor variable instead of a type variable. This is what I wanted to illustrate in a more abstract settings. I am feeling this may be a general trick-of-the-trade that Clean programmers may want to be aware of :) Best regards, and thank you for your patient explanations. (I feel kind of stupid at times.) Fabien Todescato > -----Message d'origine----- > De: Sjaak Smetsers [SMTP:sjakie@cs.kun.nl] > Date: jeudi 23 janvier 2003 12:41 > À: Fabien Todescato > Cc: clean-list@cs.kun.nl > Objet: Re: [clean-list] About semantic restrictions on type > classes. > > Dear Fabian, > > >In §6.11 of the Clean Language Report 2.1, it is said that : > > > > A type instance of an overloaded type must be a flat type , > i.e. a > >type of the form T a1...an where ai are type variables which are all > >different. > > In Clean we have the same restriction on instance types as in Haskell. I > don't know whether this restriction is fundamental, what i do know is that > > the current implementation of Clean cannot be extended (easily) in such a > way that it can deal with 'overlapping' instance types. > > >supposing I have the following : > > > >class k x y :: x y -> y > > > >The above-mentionned restriction prevents the definition of : > > > >instance k x ( t x ) > > > >where t is some type constructor. > > > >Now, if the class k is instead defined as follows : > > > >class k x t y :: x ( t y ) -> t y > > > >I can write : > > > >instance k x t y. > > So what? > > In the first case your (illegal) instance would have type > > x ( t x ) -> ( t x ) > > whereas in the second case it has type > > x ( t y ) -> t y > > Two different instances, so what are you trying to illustrate? > > >That is, using type-constructor classes may provide in some cases a > >workaround to the limitations imposed by the 'flat type' semantic > >restriction above. > > I don't see your point. > > Regards, > > Sjaak Smetsers From EZuurbier@Abz.nl Fri, 24 Jan 2003 09:21:36 +0100 Date: Fri, 24 Jan 2003 09:21:36 +0100 From: Erik Zuurbier EZuurbier@Abz.nl Subject: [clean-list] Synonym types as instances This message is in MIME format. Since your mail reader does not understand this format, some or all of this message may not be legible. ------_=_NextPart_001_01C2C381.9C49B970 Content-Type: text/plain In papers about parser combinators based on Haskell, usually a class is defined along the following lines (here in Clean syntax): class P p where fail :: p s r alt :: (p s r) (p s r) -> p s r sq :: (p s r) (r -> p s t) -> p s t suc :: r -> p s r Never mind the precise details here. Then an instance for a concrete parser-type should be made. But the only concrete types I can imagine here are synonym-types, because parsers are functions. For 'instance': :: Parser s r :== [s] -> [(r,[s])] // the traditional list-of-successes implementation instance P Parser where fail = \ss -> [] alt p1 p2 = \ss -> (p1 ss) ++ (p2 ss) sq p f = \ss -> [f r1 ss1 \\ (r1,ss1) <- p ss] suc r = \ss -> [(r,ss)] Last time I tried something like this in Clean, the compiler complained: Error [tests.icl,14,P]: Parser type synonym used as instance My question is: is this a serious disadvantage of Clean compared to Haskell? Regards Erik Zuurbier ------_=_NextPart_001_01C2C381.9C49B970 Content-Type: text/html Content-Transfer-Encoding: quoted-printable Synonym types as instances

In papers about parser combinators = based on Haskell, usually a class is defined along the following lines = (here in Clean syntax):

class P p where
        fail :: p s r
        alt :: (p s r) (p s r) -> p s r
        sq :: (p s r) (r -> p s t) -> p s t
        suc :: r -> p s r
       =20
Never mind the precise details here. = Then an instance for a concrete parser-type should be made. But the = only concrete types I can imagine here are synonym-types, because = parsers are functions. For 'instance':

:: Parser s r :=3D=3D [s] -> = [(r,[s])]      // the traditional = list-of-successes implementation

instance P Parser
where   = fail            =3D = \ss -> []
        alt p1 p2       =3D \ss = -> (p1 ss) ++ (p2 ss)
        sq p f          = =3D \ss -> [f r1 ss1 \\ (r1,ss1) <- p ss]
        suc     = r       =3D \ss -> [(r,ss)]

Last time I tried something like this = in Clean, the compiler complained:

Error [tests.icl,14,P]: Parser type = synonym used as instance

My question is: is this a serious = disadvantage of Clean compared to Haskell?

Regards Erik Zuurbier
 

------_=_NextPart_001_01C2C381.9C49B970-- From EZuurbier@Abz.nl Fri, 24 Jan 2003 12:02:21 +0100 Date: Fri, 24 Jan 2003 12:02:21 +0100 From: Erik Zuurbier EZuurbier@Abz.nl Subject: [clean-list] RE: MySQL This message is in MIME format. Since your mail reader does not understand this format, some or all of this message may not be legible. ------_=_NextPart_001_01C2C398.1127EDF0 Content-Type: text/plain Christian, you wrote >Dear Clean-Experts, can anyone tell me where I can get information how to access a MySQL Database from Clean? This question has not been answered sofar. But I am affraid I have to disappoint you altogether. In Clean you can read and write files with very basic operations such as 'read the next character', 'append an integer i', 'reposition the file pointer to p'. To my knowledge there is no library designed to read and or update any specific file format, be it a Word document, an Excel spreadsheet or an SQL database. Regards Erik Zuurbier ------_=_NextPart_001_01C2C398.1127EDF0 Content-Type: text/html Content-Transfer-Encoding: quoted-printable RE: MySQL

Christian, you wrote

>Dear Clean-Experts, can anyone = tell me where I can get information how to access a MySQL Database from = Clean?

This question has not been answered = sofar. But I am affraid I have to disappoint you altogether. In Clean = you can read and write files with very basic operations such as 'read = the next character', 'append an integer i', 'reposition the file = pointer to p'.

To my knowledge there is no library = designed to read and or update any specific file format, be it a Word = document, an Excel spreadsheet or an SQL database.

Regards Erik Zuurbier
 

------_=_NextPart_001_01C2C398.1127EDF0-- From bjpop@cs.mu.OZ.AU Fri, 24 Jan 2003 23:08:02 +1100 (EST) Date: Fri, 24 Jan 2003 23:08:02 +1100 (EST) From: Bernard James POPE bjpop@cs.mu.OZ.AU Subject: [clean-list] Re: Synonym types as instances > Never mind the precise details here. Then an instance for a concrete > parser-type should be made. But the only concrete types I can imagine here > are synonym-types, because parsers are functions. For 'instance': > > :: Parser s r :== [s] -> [(r,[s])] // the traditional list-of-successes > > My question is: is this a serious disadvantage of Clean compared to Haskell? If you are talking about Haskell 98 then the language forbids the instantiation of type classes with synonyms, see section 4.3.2, of the Haskell 98 Language Report. Though many implementations relax this restriction. However, in Haskell 98 there is the "newtype" construct: newtype Parser s r = P ([s] -> [(r, [s])]) The constructor P is only present at compile time, it is not present in the runtime representation of a value of type 'Parser s r'. So at runtime you can say that a value of type 'Parser s r' has the same "representation" as a value of type '[s] -> [(r, [s])]'. Now it is perfectly fine to instantiate a class with a type declared using the newtype construct. I don't remember whether Clean has a similar construct to Haskell 98's newtype but I would be surprised if it didn't. Perhaps if it is not there it could be simulated with strictness annotations on ordinary algebraic type declarations. Cheers, Bernie. From bpr@artisan.com Fri, 24 Jan 2003 08:36:39 -0800 Date: Fri, 24 Jan 2003 08:36:39 -0800 From: Brian Rogoff bpr@artisan.com Subject: [clean-list] Re: Synonym types as instances It was for exactly this reason that I asked some similar questions last summer, under the subject of Re: More translation questions (Was Re: [clean-list] translation of Haskell newtype?) Here is John's helpful reply: John van Groningen writes: > Brian Rogoff wrote: > > [... how to translate Haskell's newtype into Clean? ..] > The Clean compiler does not optimise this special case (a type with a > single strict unary constructor). However the compiler attempts to optimise > a record with a single (strict) field, by unboxing such a record if it > appears as a strict field in (another) record, or as a strict argument of > a constructor. > Strict arguments and results of functions are also unboxed for records. > > So it is better to translate newtype into a record with a strict field, > instead of a constructor. > > If you prefer to use a constructor like syntax, you could use a macro: > > NewType a :== {new_type=a} -- -- Brian From lakeland@cs.otago.ac.nz Mon, 27 Jan 2003 10:16:11 +1300 Date: Mon, 27 Jan 2003 10:16:11 +1300 From: Corrin Lakeland lakeland@cs.otago.ac.nz Subject: [clean-list] RE: MySQL -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Sat, 25 Jan 2003 00:02, Erik Zuurbier wrote: > Christian, you wrote > > >Dear Clean-Experts, can anyone tell me where I can get information how to > > access a MySQL Database from Clean? > > This question has not been answered sofar. But I am affraid I have to > disappoint you altogether. I have used clean to access a PostgreSQL database, and the same technique could be used to access MySQL. I used Clean's interface to C to transfer data, and used Postgres' C libraries to access the database. It did seem wasteful in that data got parsed and copied multiple times, but if performance is not an issue then you shouldn't need to worry about this. An alternative approach is to use MySQL's TCP libraries and communicate that way. I haven't tried this at all. Corrin -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.1 (GNU/Linux) iD8DBQE+NFAbi5A0ZsG8x8cRAkBzAJ9F+yMTqEi3hPJBjz/syISy/MvUewCfbsJj Ae9m4fEmp5Xmb9c46/P9PVo= =CDIh -----END PGP SIGNATURE----- From EZuurbier@Abz.nl Tue, 28 Jan 2003 09:26:35 +0100 Date: Tue, 28 Jan 2003 09:26:35 +0100 From: Erik Zuurbier EZuurbier@Abz.nl Subject: [clean-list] Re: Synonym types as instances This message is in MIME format. Since your mail reader does not understand this format, some or all of this message may not be legible. ------_=_NextPart_001_01C2C6A6.F89D62D0 Content-Type: text/plain Bernie, Brian, Bernie wrote: "I don't remember whether Clean has a similar construct to Haskell 98's newtype but I would be surprised if it didn't. Perhaps if it is not there it could be simulated with strictness annotations on ordinary algebraic type declarations." Brian wrote: "It was for exactly this reason that I asked some similar questions last summer, under the subject of Re: More translation questions (Was Re: [clean-list] translation of Haskell newtype?) Here is John's helpful reply: ..." Thanks very much for showing me the existing solution for my 'new' problem. I vaguely knew Haskell had the notion represented by newtypes; I just never knew it went by that name. (The name misled me as it just seems to be a macro for an existing type, but that is another matter.) I still hope the Clean-team will once provide a decent solution, so we don't need to rework our code to use this. Regards Erik Zuurbier ------_=_NextPart_001_01C2C6A6.F89D62D0 Content-Type: text/html Content-Transfer-Encoding: quoted-printable Re: Synonym types as instances

Bernie, Brian,

Bernie wrote:
"I don't remember whether Clean has a similar construct to = Haskell 98's newtype but I would be surprised if it didn't. Perhaps if = it is not there it could be simulated with strictness annotations on = ordinary algebraic type declarations."

Brian wrote:
"It was for exactly this reason that I asked some similar = questions last summer, under the subject of Re: More translation = questions (Was Re: [clean-list] translation of Haskell newtype?) Here = is John's helpful reply: ..."

Thanks very much for showing me the = existing solution for my 'new' problem. I vaguely knew Haskell had the = notion represented by newtypes; I just never knew it went by that name. = (The name misled me as it just seems to be a macro for an existing = type, but that is another matter.) I still hope the Clean-team will = once provide a decent solution, so we don't need to rework our code to = use this.

Regards Erik Zuurbier

------_=_NextPart_001_01C2C6A6.F89D62D0-- From jmg@pciusa.com Tue, 28 Jan 2003 13:24:12 -0500 Date: Tue, 28 Jan 2003 13:24:12 -0500 From: John M. Gogolin jmg@pciusa.com Subject: [clean-list] New Clean Programmer Hi folks, As is going to become painfully evident shortly, I'm rather new to the language of Clean. I've been trying to run through the exercises at the ends of the chapters in The Clean Book with mixed results. The one I'm currently working on is the second from chapter 3, which states: Define the function MakeFrequenceTable MakeFrequenceTable [a] -> [(a, Int)] | == a That makes a frequence table. The table consists of a list of tuples. Each tuple consists of an element from the original list and its frequency (percentage). E.g. Frequentietabel [1,2,3,2] = [(1,25),(2,50),(3,25)] Where I run into to trouble is the "| == a" clause. I can define the function as: MakeFrequenceTable :: [a] -> [(a, Int)] | Eq a MakeFrequenceTable [] = [] MakeFrequenceTable [x:xs] = take n (removeDup([(x, Frequence x [x:xs])] ++ MakeFrequenceTable (xs ++ [x]))) where n = length (removeDup [x:xs]) with the support functions: CountOccurences :: a [a] -> Int | == a CountOccurences f [] = 0 CountOccurences f [x:xs] | f == x = 1 + (CountOccurences f xs) = CountOccurences f xs Frequence :: a [a] -> Int | Eq a Frequence f x = 100 * (CountOccurences f x) / length x If I try to use "| == a", however, the compiler generates the error "internal overloading of "removeDup" could not be solved. After digging around some, I came up with a much shorter example that generates the same error: ShortenedList :: [a] -> [a] | == a ShortenedList list = removeDup list How is "| == a" in conflict with "| Eq a" in these cases? What fundamental piece am I not getting? Any help here would be greatly appreciated. Also, given that difference, how would one suggest writing the MakeFrequenceTable function as per requested in the text without rewriting a bunch of the library code? Thanks in advance, John From dvanarkel@mac.com Tue, 28 Jan 2003 23:53:52 +0100 Date: Tue, 28 Jan 2003 23:53:52 +0100 From: Diederik van Arkel dvanarkel@mac.com Subject: [clean-list] New Clean Programmer On Tuesday, January 28, 2003, at 07:24 PM, John M. Gogolin wrote: > Hi folks, > > As is going to become painfully evident shortly, I'm rather new to the > language of Clean. > > I've been trying to run through the exercises at the ends of the > chapters in The Clean Book with mixed results. The one I'm currently > working on is the second from chapter 3, which states: > > Define the function MakeFrequenceTable > MakeFrequenceTable [a] -> [(a, Int)] | == a > > That makes a frequence table. The table consists of a list of > tuples. Each tuple consists > of an element from the original list and its frequency > (percentage). > E.g. > Frequentietabel [1,2,3,2] = [(1,25),(2,50),(3,25)] > > Where I run into to trouble is the "| == a" clause. I can define the > function as: > > MakeFrequenceTable :: [a] -> [(a, Int)] | Eq a > MakeFrequenceTable [] = [] > MakeFrequenceTable [x:xs] = take n (removeDup([(x, Frequence x > [x:xs])] ++ MakeFrequenceTable (xs ++ [x]))) > where n = length (removeDup [x:xs]) > > with the support functions: > > CountOccurences :: a [a] -> Int | == a > CountOccurences f [] = 0 > CountOccurences f [x:xs] > | f == x = 1 + (CountOccurences f xs) > = CountOccurences f xs > > Frequence :: a [a] -> Int | Eq a > Frequence f x = 100 * (CountOccurences f x) / length x > > If I try to use "| == a", however, the compiler generates the error > "internal overloading of "removeDup" could not be solved. > > After digging around some, I came up with a much shorter example that > generates the same error: > > ShortenedList :: [a] -> [a] | == a > ShortenedList list = removeDup list > > How is "| == a" in conflict with "| Eq a" in these cases? What > fundamental piece am I not getting? Any help here would be greatly > appreciated. Also, given that difference, how would one suggest > writing > the MakeFrequenceTable function as per requested in the text without > rewriting a bunch of the library code? > > Thanks in advance, > John > Hi John, this is a rather poor error message by the compiler. What it's trying to tell you is that '== a' which you provide in your function type isn't enough to satisfy 'Eq a' required by removeDup. If you insist on having this solution and still satisfying the '== a' restriction given in the original problem you could copy the definition of removeDup from StdList and change the '<>' which leads to the 'Eq a' requirement into 'notEq' where you define notEq a b = not (a == b), this allows you to change the class restriction for both removeDup and MakeFrequenceTable to '== a'. Regards, Diederik van Arkel P.S. FrequenceTable l = frequencyTable (length l) l frequencyTable n [] = [] frequencyTable n [x:xs] = [(x,length same + 1) : frequencyTable n diff] where same = [e \\ e <- xs | e == x] diff = [e \\ e <- xs | not (e == x)] freq = 100 * (length same + 1) / n (programmed in Mail, may contain errors) From jmg@pciusa.com Tue, 28 Jan 2003 18:33:38 -0500 Date: Tue, 28 Jan 2003 18:33:38 -0500 From: John M. Gogolin jmg@pciusa.com Subject: [clean-list] New Clean Programmer Thanks Diederik, It occurred to me about 5 minutes after I sent the question that Eq is a class that's more restrictive than ==, isn't that the way it always goes? Ah well, I'm learning. While not quite complete or following the design spec of [list] -> [list], your example/suggestion does remind me that I should be playing around with list comprehensions a bit more so that I get comfortable with them. It would make my bloody program(s) a little less of a nightmare to read. Regards, John -----Original Message----- From: Diederik van Arkel [mailto:dvanarkel@mac.com] Sent: Tuesday, January 28, 2003 5:54 PM To: John M. Gogolin Cc: clean-list@cs.kun.nl Subject: Re: [clean-list] New Clean Programmer On Tuesday, January 28, 2003, at 07:24 PM, John M. Gogolin wrote: > Hi folks, > > As is going to become painfully evident shortly, I'm rather new to the > language of Clean. > > I've been trying to run through the exercises at the ends of the > chapters in The Clean Book with mixed results. The one I'm currently > working on is the second from chapter 3, which states: > > Define the function MakeFrequenceTable > MakeFrequenceTable [a] -> [(a, Int)] | == a > > That makes a frequence table. The table consists of a list of > tuples. Each tuple consists > of an element from the original list and its frequency > (percentage). > E.g. > Frequentietabel [1,2,3,2] = [(1,25),(2,50),(3,25)] > > Where I run into to trouble is the "| == a" clause. I can define the > function as: > > MakeFrequenceTable :: [a] -> [(a, Int)] | Eq a > MakeFrequenceTable [] = [] > MakeFrequenceTable [x:xs] = take n (removeDup([(x, Frequence x > [x:xs])] ++ MakeFrequenceTable (xs ++ [x]))) > where n = length (removeDup [x:xs]) > > with the support functions: > > CountOccurences :: a [a] -> Int | == a > CountOccurences f [] = 0 > CountOccurences f [x:xs] > | f == x = 1 + (CountOccurences f xs) > = CountOccurences f xs > > Frequence :: a [a] -> Int | Eq a > Frequence f x = 100 * (CountOccurences f x) / length x > > If I try to use "| == a", however, the compiler generates the error > "internal overloading of "removeDup" could not be solved. > > After digging around some, I came up with a much shorter example that > generates the same error: > > ShortenedList :: [a] -> [a] | == a > ShortenedList list = removeDup list > > How is "| == a" in conflict with "| Eq a" in these cases? What > fundamental piece am I not getting? Any help here would be greatly > appreciated. Also, given that difference, how would one suggest > writing > the MakeFrequenceTable function as per requested in the text without > rewriting a bunch of the library code? > > Thanks in advance, > John > Hi John, this is a rather poor error message by the compiler. What it's trying to tell you is that '== a' which you provide in your function type isn't enough to satisfy 'Eq a' required by removeDup. If you insist on having this solution and still satisfying the '== a' restriction given in the original problem you could copy the definition of removeDup from StdList and change the '<>' which leads to the 'Eq a' requirement into 'notEq' where you define notEq a b = not (a == b), this allows you to change the class restriction for both removeDup and MakeFrequenceTable to '== a'. Regards, Diederik van Arkel P.S. FrequenceTable l = frequencyTable (length l) l frequencyTable n [] = [] frequencyTable n [x:xs] = [(x,length same + 1) : frequencyTable n diff] where same = [e \\ e <- xs | e == x] diff = [e \\ e <- xs | not (e == x)] freq = 100 * (length same + 1) / n (programmed in Mail, may contain errors) From f.todescato@larisys.fr Fri, 31 Jan 2003 16:28:09 +0100 Date: Fri, 31 Jan 2003 16:28:09 +0100 From: Fabien Todescato f.todescato@larisys.fr Subject: [clean-list] Width of type window Dear Cleaners, Does somebody know what patch to apply in the Clean 2.0.2 WinIDE in order to increase the width of the type window ? And this to be able to read completely large inferred types. I browsed the source code but couldn't find the - if any - magic constant that sets the width of the windows. Thank you for your kind help, Fabien Todescato From diederik@cs.kun.nl Fri, 31 Jan 2003 17:21:58 +0100 Date: Fri, 31 Jan 2003 17:21:58 +0100 From: Diederik van Arkel diederik@cs.kun.nl Subject: [clean-list] Width of type window >At 04:28 PM 1/31/2003 +0100, you wrote: >>Dear Cleaners, >> >>Does somebody know what patch to apply in the Clean 2.0.2 WinIDE in order to >>increase the width of the type window ? And this to be able to read >>completely large inferred types. >> >>I browsed the source code but couldn't find the - if any - magic constant >>that sets the width of the windows. >> >>Thank you for your kind help, >> >>Fabien Todescato > >Hi Fabien, > >I guess I'm that somebody... In module EdVisualText in the definition of >computeViewDomain change MAX_LINE_WIDTH on line 56 to a larger value, >this should do the trick. Note that this changes the maximum width for all >windows that are editor-based (as the types window is). If you only want to >change it for the types window things will be more involved, let me know >if you >need this. > >Regards, > >Diederik van Arkel ooops, forgot to cc. the list... From f.todescato@larisys.fr Fri, 31 Jan 2003 17:54:56 +0100 Date: Fri, 31 Jan 2003 17:54:56 +0100 From: Fabien Todescato f.todescato@larisys.fr Subject: [clean-list] Limit on record size ? Dear Cleaners, Trying to compile some code I get a compiler crash whenever the size of some record type exceeds 36 fields, and this seemingly no matter what the type of the fields are. I regenerated the compiler with the Check Stack and Check Indices options set, but didn't get any informative error message. The compiler crashes only after the type-checking phase has been completed, that is, if my record has more than 36 items but the code is ill-typed, the compiler works properly. At the moment, I group fields in sub-records or tuples in order to decrease the number of fields of my large record, but this workaround sounds rather artificial for the application I am working on. Does somebody know if there a known limit on record size ? Best regards, Fabien Todescato From dvanarkel@mac.com Fri, 31 Jan 2003 20:18:23 +0100 Date: Fri, 31 Jan 2003 20:18:23 +0100 From: Diederik van Arkel dvanarkel@mac.com Subject: [clean-list] Limit on record size ? On Friday, January 31, 2003, at 05:54 PM, Fabien Todescato wrote: > Dear Cleaners, > > Trying to compile some code I get a compiler crash whenever the size > of some > record type exceeds 36 fields, and this seemingly no matter what the > type of > the fields are. > > I regenerated the compiler with the Check Stack and Check Indices > options > set, but didn't get any informative error message. The compiler > crashes only > after the type-checking phase has been completed, that is, if my > record has > more than 36 items but the code is ill-typed, the compiler works > properly. > > At the moment, I group fields in sub-records or tuples in order to > decrease > the number of fields of my large record, but this workaround sounds > rather > artificial for the application I am working on. > > Does somebody know if there a known limit on record size ? > > Best regards, Fabien Todescato > Hi Fabien, Clean records (and tuples) are currently limited to a maximum of 32 fields, that the compiler fails to flag your definition as an error is a bug which I believe has been fixed for the next version. I'm afraid you'll have to stick to your workaround for now as I don't think there are any plans to lift this limitation in the short term. You might want to file a bug at clean@cs.kun.nl to let the Clean team know that this limitation causes you problems. Regards, Diederik van Arkel From EZuurbier@Abz.nl Tue, 4 Feb 2003 16:20:59 +0100 Date: Tue, 4 Feb 2003 16:20:59 +0100 From: Erik Zuurbier EZuurbier@Abz.nl Subject: [clean-list] Transform to CPS This message is in MIME format. Since your mail reader does not understand this format, some or all of this message may not be legible. ------_=_NextPart_001_01C2CC61.055CD860 Content-Type: text/plain Hi cleaners Does anybody of you know of a systematic way to transform a function (and its context) to a version using continuations - assuming that performance improves? And is there a way to systematically identify opportunities for such transformations? For instance, I know how to write a function that lists all items of a tree: :: Tree a = Nil | Node (Tree a) a (Tree a) tree2list :: (Tree a) -> [a] tree2list Nil = [] tree2list (Node left a right) = (tree2list left) ++ [a] ++ (tree2list right) and then how to speed this up using a continuation: tree2list` :: (Tree a) [a] -> [a] tree2list` Nil cont = cont tree2list` (Node left a right) cont = tree2list` left [a:tree2list` right cont] to be called with an empty list as its second parameter. But identifying and carrying out this transformation to me looks more like black magic than a craft. Regards Erik Zuurbier ------_=_NextPart_001_01C2CC61.055CD860 Content-Type: text/html Content-Transfer-Encoding: quoted-printable Transform to CPS

Hi cleaners

Does anybody of you know of a = systematic way to transform a function (and its context) to a version = using continuations - assuming that performance improves? And is there = a way to systematically identify opportunities for such = transformations?

For instance, I know how to write a = function that lists all items of a tree:

:: Tree a =3D Nil | Node (Tree a) a = (Tree a)

tree2list :: (Tree a) -> [a]
tree2list Nil =3D []
tree2list (Node left a right) =3D = (tree2list left) ++ [a] ++ (tree2list right)

and then how to speed this up using a = continuation:

tree2list` :: (Tree a) [a] -> = [a]
tree2list` Nil cont =3D cont
tree2list` (Node left a right) cont = =3D tree2list` left [a:tree2list` right cont]

to be called with an empty list as its = second parameter.

But identifying and carrying out this = transformation to me looks more like black magic than a craft.

Regards Erik Zuurbier

------_=_NextPart_001_01C2CC61.055CD860-- From claus.reinke@talk21.com Tue, 4 Feb 2003 21:37:30 -0000 Date: Tue, 4 Feb 2003 21:37:30 -0000 From: Claus Reinke claus.reinke@talk21.com Subject: [clean-list] Transform to CPS This is a multi-part message in MIME format. ------=_NextPart_000_0050_01C2CC95.9EEE3580 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Transform to CPSThere are several CPS transforms for the = lambda-calculus, encoding=20 different reduction strategies, but in your example the 'magic' is = simply in the list representation. You replace the standard binary list = representation by a "continuation-passing" representation (difference-list, in Prolog = terms;), which abstracts over the ends of lists, thus simplifying appends. If you forgive the Haskellish pseudo-code (. is function composition, : = is cons, \x->.. is lambda abstraction): {orig} tree2list :: (Tree a) -> [a]=20 tree2list Nil =3D []=20 tree2list (Node left a right) =3D (tree2list left) ++ [a] ++ (tree2list = right)=20 {new representation} nil =3D id cons h t =3D (h:) . t l +++ r =3D l . r {switch to new repr} tree2list Nil =3D nil tree2list (Node left a right) =3D (tree2list left) +++ (cons a = (tree2list right)) {definitions of nil, +++} tree2list Nil =3D id tree2list (Node left a right) =3D (tree2list left) . (cons a (tree2list = right)) {definitions of id,.} tree2list Nil =3D \l->l tree2list (Node left a right) =3D \l-> (tree2list left (cons a = (tree2list right) l) {definition of cons} tree2list Nil =3D \l->l tree2list (Node left a right) =3D \l-> (tree2list left (((a:) . = ((tree2list right)) l) {definition of .} tree2list Nil =3D \l->l tree2list (Node left a right) =3D \l-> (tree2list left (a: (tree2list = right l)) {back to Clean} tree2list` :: (Tree a) [a] -> [a]=20 tree2list` Nil cont =3D cont=20 tree2list` (Node left a right) cont =3D tree2list` left [a:tree2list` = right cont]=20 to be called with an empty list as its second parameter.=20 But identifying and carrying out this transformation to me looks more = like black magic than a craft.=20 hth,=20 Claus ------=_NextPart_000_0050_01C2CC95.9EEE3580 Content-Type: text/html; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Transform to CPS
There are several CPS transforms for = the=20 lambda-calculus, encoding =
different reduction strategies, but in = your example=20 the 'magic' is simply
in the list representation. You replace = the=20 standard binary list representation
by a "continuation-passing"=20 representation (difference-list, = in Prolog=20 terms;),
which abstracts over the ends of lists, = thus=20 simplifying appends.
 
If you forgive the Haskellish = pseudo-code (. is=20 function composition, : is cons,
\x->.. is lambda = abstraction):
 
{orig}
tree2list :: (Tree a) -> [a] =
tree2list Nil =3D []
tree2list (Node left a right) =3D (tree2list left) ++ [a] ++ = (tree2list=20 right)
 
{new representation}
nil =3D id
cons h t =3D (h:) . t
l +++ r =3D l . r
 
{switch to new repr}
tree2list Nil =3D nil
tree2list (Node=20 left a right) =3D (tree2list left) +++ (cons a (tree2list = right))
 
{definitions of nil, +++}
tree2list Nil =3D id
tree2list (Node left a right) =3D (tree2list left) . (cons = a=20 (tree2list right))
 
{definitions of id,.}
tree2list Nil = =3D=20 \l->l
tree2list (Node left a = right) =3D=20 \l-> (tree2list left (cons a (tree2list right) = l)
 
{definition of cons}
tree2list Nil = =3D=20 \l->l
tree2list (Node left a = right) =3D=20 \l-> (tree2list left (((a:) . ((tree2list right)) = l)
 
{definition of .}
tree2list Nil =3D=20 \l->l
tree2list (Node left a = right) =3D=20 \l-> (tree2list left (a: (tree2list right l))
 
{back to Clean}

tree2list` :: (Tree a) [a] -> = [a]=20
tree2list` Nil cont =3D cont =
tree2list` (Node left a right) cont =3D = tree2list` left=20 [a:tree2list` right cont]

to be called with an empty list as its = second=20 parameter.

But identifying and carrying out this=20 transformation to me looks more like black magic than a craft.=20

hth,=20

Claus

 

------=_NextPart_000_0050_01C2CC95.9EEE3580-- From m.verver@student.utwente.nl Tue, 4 Feb 2003 18:20:36 +0100 Date: Tue, 4 Feb 2003 18:20:36 +0100 From: Maks Verver m.verver@student.utwente.nl Subject: [clean-list] Transform to CPS Hi Erik, I think the characteristics to look for, in the situation you described, would be: 1. You are concatenating two lists, the first of which is non-trivial (and might be very large) 2. The construction of the second list does not depend upon the first list (ie. it's not a problem to construct the second list first) 3. You use a recursive function with a terminating condition that returns the empty list, to construct your first list In this scenario, it is clear that you could evaluate the second list first, and pass it on to the construction function for the first list, which would then use it as the result's tail in the terminating condition instead of the empty list. You have now avoided the concatenation altogether. If this is significantly faster, depends a bit on what you are doing. If computating the list elements is hard, the relative cost of concatenating the lists will be pretty low. In your example: :: Tree a = Nil | Node (Tree a) a (Tree a) tree2list :: (Tree a) -> [a] tree2list Nil = [] tree2list (Node left a right) = (tree2list left) ++ [a] ++ (tree2list right) I would first evaluate the concatenation of [a] with the list for the right, branch: tree2list (Node left a right) = (tree2list left) ++ [a : tree2list right] Now, I have a situation to match the criteria. I first modify my terminating condation: tree2list Nil tail = tail (Note that 'tail' used to be the empty list, []) Finally, I modify the recursive definition, taking advantage of the fact that I can specify the tail which is to be append to the result, instead of manually appending it with the ++-operator: tree2list (Node left a right) tail = tree2list left [a : tree2list right tail] I'm pretty sure the criteria I mentioned can be loosened a bit, so they apply in more situations (when more than just a list is returned, for example), but I find this 'pattern' can be applied in many cases already in this form. Recognizing and implementing it requires a bit of insight and creativity, but I think it's largely a mechanical process. In essence, you do nothing more than create a function that uses a tail specified by the caller to terminate your lists, and take advantage of that in the implementation. Does anyone have examples of other optimizations that can be generalised in this way? Is there such a thing as a standard library of 'functional patterns'? Publications perhaps? Kind regards, Maks Verver. -----Original Message----- From: clean-list-admin@cs.kun.nl [mailto:clean-list-admin@cs.kun.nl] On Behalf Of Erik Zuurbier Sent: dinsdag 4 februari 2003 16:21 To: 'clean-list@cs.kun.nl' Subject: [clean-list] Transform to CPS Hi cleaners Does anybody of you know of a systematic way to transform a function (and its context) to a version using continuations - assuming that performance improves? And is there a way to systematically identify opportunities for such transformations? For instance, I know how to write a function that lists all items of a tree: :: Tree a = Nil | Node (Tree a) a (Tree a) tree2list :: (Tree a) -> [a] tree2list Nil = [] tree2list (Node left a right) = (tree2list left) ++ [a] ++ (tree2list right) and then how to speed this up using a continuation: tree2list` :: (Tree a) [a] -> [a] tree2list` Nil cont = cont tree2list` (Node left a right) cont = tree2list` left [a:tree2list` right cont] to be called with an empty list as its second parameter. But identifying and carrying out this transformation to me looks more like black magic than a craft. Regards Erik Zuurbier From bpr@artisan.com Tue, 4 Feb 2003 09:37:38 -0800 Date: Tue, 4 Feb 2003 09:37:38 -0800 From: Brian Rogoff bpr@artisan.com Subject: [clean-list] Transform to CPS Erik Zuurbier writes: > Hi cleaners > > Does anybody of you know of a systematic way to transform a function (and > its context) to a version using continuations Yup. It's called, surprisingly, the CPS transform. Probably every intermediate functional programmer should know how to beat a simple function into CPS in their pet language. If you know Scheme, I'd suggest you pick up a copy of "Essentials of Programming Languages" by Friedman, Wand and Haynes, and read it cover to cover, or, if you're lazy, just skip to those later chapters. If you're into the history of ideas, there is a paper by Reynolds called "The Discoveries of Continuations", and also one called "Definitional Interpreters", that you should be able to find on the web. -- -- Brian From ok@cs.otago.ac.nz Wed, 5 Feb 2003 13:16:36 +1300 (NZDT) Date: Wed, 5 Feb 2003 13:16:36 +1300 (NZDT) From: Richard A. O'Keefe ok@cs.otago.ac.nz Subject: [clean-list] Transform to CPS Erik Zuurbier wrote: Does anybody of you know of a systematic way to transform a function (and its context) to a version using continuations - assuming that performance improves? The CPS transformation was described in the famous RABBIT thesis, which is available for download. It has been described and improved in many papers. Check CiteSeer and look for 'CPS' or 'Continuation Passing'. For instance, I know how to write a function that lists all items of a tree: :: Tree a = Nil | Node (Tree a) a (Tree a) tree2list :: (Tree a) -> [a] tree2list Nil = [] tree2list (Node left a right) = tree2list left ++ [a] ++ tree2list right and then how to speed this up using a continuation: tree2list` :: (Tree a) [a] -> [a] tree2list` Nil cont = cont tree2list` (Node left a right) cont = tree2list` left [a:tree2list` right cont] to be called with an empty list as its second parameter. That's accumulator passing, not continuation passing. "cont" would more helpfully be called "acc". Here's continuation passing: tree2list`` :: (Tree a) -> ([a] -> b) -> b tree2list`` Nil cont = cont [] tree2list`` (Node left a right) cont = tree2list`` right (\rr -> tree2list`` left (\ll -> cont (ll ++ [a] ++ rr))) Accumulator passing and continuation passing can be combined: tree2list``` :: (Tree a) -> [a] -> ([a] -> b) -> b tree2list``` Nil acc cont = cont acc tree2list``` (Node left a right) acc cont = tree2list``` right acc (\acc` -> tree2list``` left [a:acc`] cont) But identifying and carrying out this transformation to me looks more like black magic than a craft. Isn't something like this described in the classic Burstall and Darlington paper? It was used systematically in Boyer & Moore's work on converting Fortran so that the Boyer-Moore theorem prover could process it. The Prolog analogue is "list differences", described in The Craft of Prolog and most other Prolog books. Avoiding ++ by passing a list accumulator is described in several Haskell textbooks. There is of course the famous paper "Why listlessness is better than laziness" and subsequent work leading to "Deforestation" (source to source transformation to eliminate data structure building). I believe GHC does deforestation, and I'm pretty sure that the Melbourne Mercury compiler does too. From maldim@gmx.net Wed, 05 Feb 2003 09:48:12 +0200 Date: Wed, 05 Feb 2003 09:48:12 +0200 From: Dmitry Malenko maldim@gmx.net Subject: [clean-list] Undefined value and theorem proving Hi, All! In an example given in "Theorem Proving for Functional Programmers - SPARKLE: A Functional Theorem Prover" restriction is put that take :: Int ![a] -> [a] does not get an undefined value as its first argument. So I wonder how it is possible to call take with undefined value? And in general, what operations in Clean can result with undefined expression? -- Best regards, Dmitry Malenko. +----------------------------------------------------+ Registered Linux user #258004 ALT Linux Team http://www.altlinux.ru +----------------------------------------------------+ Do you guys know what you're doing, or are you just hacking? From maartenm@cs.kun.nl Wed, 5 Feb 2003 09:58:34 +0100 Date: Wed, 5 Feb 2003 09:58:34 +0100 From: Maarten de Mol maartenm@cs.kun.nl Subject: [clean-list] Undefined value and theorem proving Hello Dmitry, > Hi, All! > > In an example given in "Theorem Proving for Functional Programmers - > SPARKLE: A Functional Theorem Prover" restriction is put that > > take :: Int ![a] -> [a] > > does not get an undefined value as its first argument. > > So I wonder how it is possible to call take with undefined value? And in > general, what operations in Clean can result with undefined expression? The magic black box functions 'undef' and 'abort' from the module StdMisc return the undefined value. For example, 'take undef [5]' will reduce to 'undef', while 'take undef []' will reduce to '[]'. There are other possibilities to produce the undefined value in Clean: * Calling a function with a pattern that does not match. * Using a case distinction in which no alternative matches. Basically, anything that terminates your program with an error message can be regarded as producing the undefined value. Greetings, Maarten de Mol > > -- > Best regards, Dmitry Malenko. > +----------------------------------------------------+ > Registered Linux user #258004 > ALT Linux Team http://www.altlinux.ru > +----------------------------------------------------+ > Do you guys know what you're doing, or are you just hacking? > > > > _______________________________________________ > clean-list mailing list > clean-list@cs.kun.nl > http://www.cs.kun.nl/mailman/listinfo/clean-list > From karczma@info.unicaen.fr Wed, 05 Feb 2003 11:55:08 +0100 Date: Wed, 05 Feb 2003 11:55:08 +0100 From: Jerzy Karczmarczuk karczma@info.unicaen.fr Subject: [clean-list] Transform to CPS Erik Zuurbier wrote: > Does anybody of you know of a systematic way to transform a function > (and its context) to a version using continuations - assuming that > performance improves? And is there a way to systematically identify > opportunities for such transformations? > > For instance, I know how to write a function that lists all items of a > tree: > > :: Tree a = Nil | Node (Tree a) a (Tree a) > > tree2list :: (Tree a) -> [a] > tree2list Nil = [] > tree2list (Node left a right) = (tree2list left) ++ [a] ++ (tree2list > right) > > and then how to speed this up using a continuation: > > tree2list` :: (Tree a) [a] -> [a] > tree2list` Nil cont = cont > tree2list` (Node left a right) cont = tree2list` left [a:tree2list` > right cont] > > to be called with an empty list as its second parameter. > > But identifying and carrying out this transformation to me looks more > like black magic than a craft. Well, first of all, I wouldn't call this transformation a 'continuation', this is a variant of optimization with an accumulating parameter. It is quite simple to do when you have an *associative* operator involved, here the concatenation. The same principle can be used to optimize the power, the factorial, etc. All has been formalized by Darlington and Burstall many years ago. I can - just for some general culture - give you a meta-recipe which I use with my students (if all of us are in good mood...) Say, fac n = if n==0 then 1 else n*fac(n-1) (sorry for some haskellianisms on the Clean list...) 1. GENERALIZE Introduce a more general function with such semantics: facc n s = s * fac n MIND YOU! This is *not* its definition, but its conceptual meaning. In fact, the real definition is inverted: fac n = facc n 1 2. UNFOLD facc n s = if n==0 then s*1 else s*n*fac(n-1) = if n==0 then s else facc (n-1) (n*s) That's it. Note how the associativity came into play. For your trees the generalization stage is trlist' t buf = tree2list t ++ buf and you follow the same reasoning. === The CPS transformation - *not unrelated* to the accumulating parameter stuff, would mean faccps n cnt = cnt (fac n) fac n = faccps n id where id x = x faccps n cnt = if n==0 then cnt 1 else cnt (n*fac(n-1)) = if n==0 then cnt 1 else faccps (n-1) (cnt . (n *)) In such a way it became tail-recursive, but the cost is high, it generates growing thunks on the heap, so this cost is comparable with the stack-based approach. But now it can be further improved... I suggest that you look not only some papers and sites on the CPS conversion, but also on some ancient and venerable work done by Burstall and Darlington on program improvement. JACM '1977 Something on-line http://citeseer.nj.nec.com/burstall77transformation.html http://www.diku.dk/topps/activities/pgmtrans/ (here you might find a pdf [at DIKU] with some stuff) Claus Reinke makes some parallels with the differential lists in Prolog. I would be a bit careful here. The incomplete structures in Prolog may be used in such a way, they are able to transform copying_and_copying_and_copying append into something like append! (in Scheme), but their traditional usage requires the existence of a "non-instantiated logical variable", which does not exists in functional languages. So, the parallels, analogies, etc. are not very natural, and require some skills, while - it seems - you want samething quite automatic and straightforward. I *do not* criticize Claus, I just suggest that it might not be the most natural way. At any rate, it was not so clear for my students, although they grasped the idea quite quickly. Jerzy Karczmarczuk Oh, my goodness, now I see the remaining postings. Richard O'Keefe quotes D&B as well. Oh well, I send it anyway... From fjh@cs.mu.OZ.AU Thu, 6 Feb 2003 05:18:36 +1100 Date: Thu, 6 Feb 2003 05:18:36 +1100 From: Fergus Henderson fjh@cs.mu.OZ.AU Subject: [clean-list] Transform to CPS On 05-Feb-2003, Richard A. O'Keefe wrote: > There is of course the famous paper "Why listlessness is better than laziness" > and subsequent work leading to "Deforestation" (source to source transformation > to eliminate data structure building). I believe GHC does deforestation, and > I'm pretty sure that the Melbourne Mercury compiler does too. I'm not entirely sure, but I think GHC does only a simplified form of deforestation known as "short-cut deforestation", which would not be able to optimize calls to (the obvious Haskell translation of) the tree2list function posted by the originator of this thread. If my recollection is correct, GHC can only optimize away intermediate lists, not other intermediate data structures (e.g. trees), and only if they are constructed and consumed by list processing functions which are ultimately defined in terms of a couple of built-in higher-order functions, not if they are constructed or consumed using manual first-order code that processes each element in turn. But I could be wrong about that, or it may have changed in more recent releases of GHC. The Melbourne Mercury compiler has had support for deforestation since Mercury 0.8, released on 18 November 1998. It supports a quite general form of deforestation that is capable of deforesting intermediate data structures of user-defined types such as trees. However, I just noticed that in the current version, 0.11, the optimization is not working properly -- for the test case that I just tried (see below), the Mercury compiler optimizes the two traversals into a single traversal, avoiding the unnecessary traversal of the intermediate data structure, but it fails to optimize away the *construction* of the intermediate data structure. This problem appears to be a regression in Mercury release 0.11 -- it seems to work correctly in 0.10. Hopefully it will be something simple which we can easily fix for 0.11.1. :- module t2l. :- interface. :- import_module list. :- type tree(T) ---> nil ; node(tree(T), T, tree(T)). :- func tree2list(tree(T)) = list(T). :- func list2tree(list(T)) = tree(T). :- func list2list(list(T)) = list(T). :- implementation. tree2list(nil) = []. tree2list(node(Left, A, Right)) = tree2list(Left) ++ [A] ++ tree2list(Right). list2tree([]) = nil. list2tree([X|Xs]) = node(nil, X, list2tree(Xs)). % Deforestation optimization ought to be able to optimize away % the intermediate tree here. list2list(L) = tree2list(list2tree(L)). -- Fergus Henderson | "I have always known that the pursuit The University of Melbourne | of excellence is a lethal habit" WWW: | -- the last words of T. S. Garp. From fjh@cs.mu.OZ.AU Thu, 6 Feb 2003 05:33:38 +1100 Date: Thu, 6 Feb 2003 05:33:38 +1100 From: Fergus Henderson fjh@cs.mu.OZ.AU Subject: [clean-list] Transform to CPS On 05-Feb-2003, Jerzy Karczmarczuk wrote: > Well, first of all, I wouldn't call this transformation a 'continuation', > this is a variant of optimization with an accumulating parameter. It is > quite simple to do when you have an *associative* operator involved, here > the concatenation. The same principle can be used to optimize the power, > the factorial, etc. All has been formalized by Darlington and Burstall > many years ago. This optimization, which we call "accumulator introduction", has been implemented in the Mercury compiler. If the user declares that an operation is associative, the Mercury compiler can apply the optimization automatically. See the following reference: * "Making Mercury programs tail recursive". Peter Ross, David Overton and Zoltan Somogyi. Proceedings of the Ninth International Workshop on Logic-based Program Synthesis and Transformation, Venice, Italy, September 1999. While I'm at it, let me also give a reference for the Mercury compiler's deforestation optimization which I mentioned in my previous mail: * "Optimization of Mercury programs". Simon Taylor. Honours report. Department of Computer Science, University of Melbourne, November 1998. -- Fergus Henderson | "I have always known that the pursuit The University of Melbourne | of excellence is a lethal habit" WWW: | -- the last words of T. S. Garp. From fjh@cs.mu.OZ.AU Thu, 6 Feb 2003 18:09:26 +1100 Date: Thu, 6 Feb 2003 18:09:26 +1100 From: Fergus Henderson fjh@cs.mu.OZ.AU Subject: [clean-list] Transform to CPS I wrote: > The Melbourne Mercury compiler has had support for deforestation since > Mercury 0.8 [...] However, I just noticed that in the current version, > 0.11, the optimization is not working properly [...] Hopefully it will > be something simple which we can easily fix for 0.11.1. It was -- Simon Taylor quickly found and fixed the problem. It turns out that there's also a simple work-around for 0.11.0: compile with the `--no-local-constraint-propagation' option. So Richard O'Keefe's statement "I'm pretty sure that the Melbourne Mercury compiler does [deforestation] too" was correct, even for Mercury 0.11.0 ;-) -- Fergus Henderson | "I have always known that the pursuit The University of Melbourne | of excellence is a lethal habit" WWW: | -- the last words of T. S. Garp. From simonpj@microsoft.com Thu, 6 Feb 2003 09:35:00 -0000 Date: Thu, 6 Feb 2003 09:35:00 -0000 From: Simon Peyton-Jones simonpj@microsoft.com Subject: [clean-list] Transform to CPS | function posted by the originator of this thread. If my recollection is | correct, GHC can only optimize away intermediate lists, not other | intermediate data structures (e.g. trees), and only if they are | constructed and consumed by list processing functions which are ultimately | defined in terms of a couple of built-in higher-order functions, not | if they are constructed or consumed using manual first-order code that | processes each element in turn. Correct. | The Melbourne Mercury compiler has had support for deforestation since | Mercury 0.8, released on 18 November 1998. It supports a quite general | form of deforestation that is capable of deforesting intermediate | data structures of user-defined types such as trees. I didn't know that -- I'm well impressed. One the hardest aspects, I found, was to guarantee that the transformation would never make things worse. For example, transforming a function that consumes a data structure directly, to use a fold instead, makes it less efficient. Ditto on the 'production' side. So there has to be a way to make sure that when fusion does not happen, the program is no less efficient than before. Is this the case in Mercury? Is the MSc thesis you refer to available online? Simon From fjh@cs.mu.OZ.AU Thu, 6 Feb 2003 23:09:59 +1100 Date: Thu, 6 Feb 2003 23:09:59 +1100 From: Fergus Henderson fjh@cs.mu.OZ.AU Subject: [clean-list] Transform to CPS On 06-Feb-2003, Simon Peyton-Jones wrote: > [Fergus Henderson:] > | The Melbourne Mercury compiler has had support for deforestation since > | Mercury 0.8, released on 18 November 1998. It supports a quite general > | form of deforestation that is capable of deforesting intermediate > | data structures of user-defined types such as trees. > > I didn't know that -- I'm well impressed. One the hardest aspects, I > found, was to guarantee that the transformation would never make things > worse. For example, transforming a function that consumes a data > structure directly, to use a fold instead, makes it less efficient. > Ditto on the 'production' side. So there has to be a way to make sure > that when fusion does not happen, the program is no less efficient than > before. Is this the case in Mercury? We don't use short-cut style (e.g. fold/build) deforestation. We don't convert code to use `fold', for example. Instead, we explicitly look for code which contains two procedure calls, one of which produces a data structure, and the other of which switches on the data structure produced, and replaces this with a new procedure whose body combines the two. This can slightly reduce efficiency by increasing the code size, and also by increasing the number of arguments (and hence increasing register pressure). However, the optimization is only applied if the new procedure's body can be simplified. It is these simplifications which improve efficiency. In particular, we try to push the switch that originally came from the consumer procedure into each branch of the producer procedure's body. This is more code duplication, which again only reduces efficiency. But if in some branch of the original producer procedure's body, the intermediate data structure is bound to a term with a known top-level functor, then both the construction and the switch can be eliminated in that branch, instead replacing the switch with the matching case. That's where we get a big win. The compiler also identifies call pairs in the new procedure which call the original producer and consumer procedures, and replaces them with recursive calls to the new procedure. Since we are apply the transformation to paired consumers/producers, rather than to individual consumers or individual producers, it's easy enough to ensure that we only apply it in cases when it leads to fusion or other simplifications. However, even when fusion does occur, it's not easy to be sure that it is going to improve performance overall. At this point we resort to some heuristics. We have a simple cost model for the cost of each operation, and we compare the cost and size of the original code with the cost and size of the transformed code. We only use the transformed code if there is an improvement in cost which our heuristics judge is sufficient to justify the increase in code size, if any. (If we had more information, e.g. profiling feedback, it would in theory be possible to use this information in the cost modelling to get a more accurate heuristic.) So, because the heuristic is not perfect, when the transformation is applied, it could potentially make the program a little less efficient. However, any such efficiency loss would only be a small constant factor, I think, and in most cases it is a win, sometimes a major one. > Is the MSc thesis you refer to available online? Yes, sorry, I forgot to paste in the URL: . Note that it is a BSc(Hons) thesis, not an MSc thesis. -- Fergus Henderson | "I have always known that the pursuit The University of Melbourne | of excellence is a lethal habit" WWW: | -- the last words of T. S. Garp. From brennie@dcsi.net.au Tue, 11 Feb 2003 21:45:13 +1100 Date: Tue, 11 Feb 2003 21:45:13 +1100 From: Bruce Gordon Rennie brennie@dcsi.net.au Subject: [clean-list] Accessing OpenGL functions Dear All, I have only recently come across CLEAN and the CLEAN Game library. As I run Windows NT4.0, using the DirectX libraries are not really an option. I am wanting to setup the CLEAN Games library to use one of the display systems, OpenGL, SDL, etc. However, I am finding some difficulty in obtaining the information needed to do this. I get the impression from what I have so far found is that I will need to create one or more mapping library files and possibly a number of .abc files. I want to be able to run the programs developed on both the NT4.0 box (mine) and the Linux box ( my childrens) and even possibly on the Macs when I get around to rebuilding them. Does anyone know of any reference materials that explain the low-level interfacing between CLEAN and the OS libraries. The purpose I am doing this for is to enable my thirteen year old son (youngest) to learn games development ( in a fun way - he has a dream of making much money from this endeavour as well as enjoying the process of making his own games) -- Bruce Rennie ( from God's Own Country Downunder ) Disciple of Jesus Christ in Training The Cross of Jesus Christ - Salvation for all men. Song of Solomon ( Song of Songs ) - The greatest Love Story Ever and a story for our times. Be a GOD Chaser. From EZuurbier@Abz.nl Fri, 14 Feb 2003 11:06:04 +0100 Date: Fri, 14 Feb 2003 11:06:04 +0100 From: Erik Zuurbier EZuurbier@Abz.nl Subject: [clean-list] Re: Accessing OpenGL functions This message is in MIME format. Since your mail reader does not understand this format, some or all of this message may not be legible. ------_=_NextPart_001_01C2D410.AF4ED6A0 Content-Type: text/plain Bruce Rennie wrote: === Dear All, I have only recently come across CLEAN and the CLEAN Game library. As I run Windows NT4.0, using the DirectX libraries are not really an option. I am wanting to setup the CLEAN Games library to use one of the display systems, OpenGL, SDL, etc. However, I am finding some difficulty in obtaining the information needed to do this. I get the impression from what I have so far found is that I will need to create one or more mapping library files and possibly a number of .abc files. I want to be able to run the programs developed on both the NT4.0 box (mine) and the Linux box ( my childrens) and even possibly on the Macs when I get around to rebuilding them. Does anyone know of any reference materials that explain the low-level interfacing between CLEAN and the OS libraries. The purpose I am doing this for is to enable my thirteen year old son (youngest) to learn games development ( in a fun way - he has a dream of making much money from this endeavour as well as enjoying the process of making his own games) ==== Bruce, None of the specialists seems to have bothered to answer you, so I'll tell you what I know. Clean is not a toy for kids. It is a very high level programming language that works completely different from languages like C++. If your son is very persevering and bright, he might be able to make it. Clean's learning curve is far from steep: it may take anyone years to become fluent in using Clean. If making money and enjoying game-making are his (only) motivations, I would strongly recommend him to look elsewhere. For using Clean, motivations should be enjoying programming itself and knowing that the intricacies of the language will challenge him for years and years to come. Regards Erik Zuurbier ------_=_NextPart_001_01C2D410.AF4ED6A0 Content-Type: text/html Content-Transfer-Encoding: quoted-printable Re: Accessing OpenGL functions

Bruce Rennie wrote:
=3D=3D=3D
Dear All,
I have only recently come across = CLEAN and the CLEAN Game library. As I run Windows NT4.0, using the = DirectX libraries are not really an option. I am wanting to setup the = CLEAN Games library to use one of the display systems, OpenGL, SDL, = etc. However, I am finding some difficulty in obtaining the information = needed to do this.

I get the impression from what I have = so far found is that I will need to create one or more mapping library = files and possibly a number of .abc files. I want to be able to run the = programs developed on both the NT4.0 box (mine) and the Linux box ( my = childrens) and even possibly on the Macs when I get around to = rebuilding them. Does anyone know of any reference materials that = explain the low-level interfacing between CLEAN and the OS = libraries.

The purpose I am doing this for is to = enable my thirteen year old son (youngest) to learn games development ( = in a fun way - he has a dream of making much money from this endeavour = as well as enjoying the process of making his own games)

=3D=3D=3D=3D
Bruce,

None of the specialists seems to have = bothered to answer you, so I'll tell you what I know.

Clean is not a toy for kids. It is a = very high level programming language that works completely different = from languages like C++. If your son is very persevering and bright, he = might be able to make it. Clean's learning curve is far from steep: it = may take anyone years to become fluent in using Clean.

If making money and enjoying = game-making are his (only) motivations, I would strongly recommend him = to look elsewhere. For using Clean, motivations should be enjoying = programming itself and knowing that the intricacies of the language = will challenge him for years and years to come.

Regards Erik Zuurbier

------_=_NextPart_001_01C2D410.AF4ED6A0-- From ahey@iee.org Mon, 17 Feb 2003 16:43:45 +0000 Date: Mon, 17 Feb 2003 16:43:45 +0000 From: Adrian Hey ahey@iee.org Subject: [clean-list] Re: Accessing OpenGL functions On Friday 14 February 2003 10:06, Erik Zuurbier wrote: > Clean is not a toy for kids. It is a very high level programming language > that works completely different from languages like C++. If your son is > very persevering and bright, he might be able to make it. Clean's learning > curve is far from steep: it may take anyone years to become fluent in using > Clean. Hello Erik, Seem's like you're trying to put people off FPL's for life. They aren't that difficult to learn and you shouldn't under estimate 13 year olds :-) As for the original question, I also have no idea how to access OpenGL from Clean. (That doesn't mean it's impossible of course.) You can do it in Haskell using HOpenGL.. http://www.haskell.org/HOpenGL/ Whether either language (Clean or Haskell) is good for gaming probably depends on the game in question. I think they'd be good for games of "intellect" (like chess,go etc). But if you need top notch real time arcade quality 3D graphics and sound effects for alien zapping style games they might not be the best choice. Regards -- Adrian Hey From m.verver@student.utwente.nl Mon, 17 Feb 2003 20:25:12 +0100 Date: Mon, 17 Feb 2003 20:25:12 +0100 From: Maks Verver m.verver@student.utwente.nl Subject: [clean-list] Re: Accessing OpenGL functions Hi everyone, Adrian Hey wrote: > Seem's like you're trying to put people off FPL's for life. > They aren't that difficult to learn and you shouldn't under > estimate 13 year olds :-) I think that if you start with an underestimation of the language's difficulty, you are likely to run into frustrating problems, which may well result in never wanting to work with the language ever again. That's not really what we want, either, is it? Ofcourse, anyone that is interested in learning a functional language should attempt to do so, but if your goal is making computer games, you might be better off looking somewhere else (at some of those easy-to-use game builder applications, for example). > As for the original question, I also have no idea how to > access OpenGL from Clean. (That doesn't mean it's impossible > of course.) You can do it in Haskell using HOpenGL.. > > http://www.haskell.org/HOpenGL/ I believe there is a tool for converting C header files to Clean as well, so you could use the C library directly from Clean, but you would completely ignore the functional programming style this way. OpenGL is very 'imperative' by design. The OpenGL 'driver' (at least at application level) has a global state that is modified by OpenGL commands from the application, wich contradicts the stateless functional paradigm. Ofcourse, you could write a 'good' functional OpenGL wrapper around the basic library. However, I think doing this well would be a tremendous effort, easily as much work as writing the game itself. > Whether either language (Clean or Haskell) is good for gaming > probably depends on the game in question. I think they'd be > good for games of "intellect" (like chess,go etc). But if you > need top notch real time arcade quality 3D graphics and sound > effects for alien zapping style games they might not be the > best choice. The Clean Game Library by Mike Wiering (http://cleangl.sourceforge.net/) shows that it is very well possible to write arcade-style games in Clean. I suppose it's not "top notch" graphics, but it's decent in terms of performance and image quality. Studying it's internals might be interesting (although I must admit I never did), as I suppose it covers much of "how things are supposed to be done" in a functional game. Unfortunately, the game library does not support anything 3D, so if producing 3D grapics is a requirement, it's not a definite answer to your problem. Nonetheles, I think it's a very good way to start, if you want to learn how to program games with a functional language. The website contains a lot of sample games, and a short tutorial. Kind regards, Maks Verver. From info@spitsbroeders.nl Mon, 17 Feb 2003 21:49:25 +0100 Date: Mon, 17 Feb 2003 21:49:25 +0100 From: Spitsbroeders info@spitsbroeders.nl Subject: [clean-list] error message when compiling: short path ??? This is a multi-part message in MIME format. ------=_NextPart_000_0049_01C2D6CE.70835F20 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Hi all, I read about Clean in C'T, I became very interested because of the very = uncommon structure of this language. I installed the software and tried = some first steps, but I didn't even manage to compile the "life-game" in = the exaples section. I was confronted with the error that a "short path" = to the compiler was not found. My system is Win 2k. I am only a = programming newbie and I guess I have to try some more, but I figure = someone else's been going through this before and might gimme a hint. Thanks i.a. Joost ------=_NextPart_000_0049_01C2D6CE.70835F20 Content-Type: text/html; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable
Hi all,
I read about Clean in C'T, I became = very interested=20 because of the very uncommon structure of this language. I installed the = software and tried some first steps, but I didn't even manage to compile = the=20 "life-game" in the exaples section. I was confronted with the error that = a=20 "short path" to the compiler was not found. My system is Win 2k. I am = only a=20 programming newbie and I guess I have to try some more, but I figure = someone=20 else's been going through this before and might gimme a = hint.
Thanks i.a.
Joost
------=_NextPart_000_0049_01C2D6CE.70835F20-- From jeremy.shaw@lindows.com Mon, 17 Feb 2003 12:20:03 -0800 Date: Mon, 17 Feb 2003 12:20:03 -0800 From: Jeremy Shaw jeremy.shaw@lindows.com Subject: [clean-list] Re: Accessing OpenGL functions Hello, I am not sure if Clean's Foreign Function Interface *IS* documented, the source may be the only reference. There has been some interest in OpenGL support for Clean, but no one has had the time to implement it yet -- and probably won't any time soon either. As Adrian mentioned, there is OpenGL support for Haskell. Clean is heavily based on Haskell, so you can easily switch to Clean if Clean ever gets OpenGL support. I would recommend the ghc compiler for use with HOpenGl (http://www.haskell.org/ghc). If you looked closely at the bottom of the HOpenGL page, you will notice that HOpenGL was written for the purpose of making 3D shoot-em-up video games. I have a little experience teaching novice programmers and have found Haskell to be easier to teach than C. It's easier to explain things like lists and recursion, than pointers and memory management. The haskell community is larger and more active than Clean. When a new version of ghc comes it, it is typically available for all supported platforms in less than a week. Both of these will make your life easier. On the other hand, if you have the time to add OpenGL support to Clean, then go for it! Clean is a bit more advanced than Haskell, and generates faster code. Jeremy Shaw. At Mon, 17 Feb 2003 16:43:45 +0000, Adrian Hey wrote: > > On Friday 14 February 2003 10:06, Erik Zuurbier wrote: > > Clean is not a toy for kids. It is a very high level programming language > > that works completely different from languages like C++. If your son is > > very persevering and bright, he might be able to make it. Clean's learning > > curve is far from steep: it may take anyone years to become fluent in using > > Clean. > > Hello Erik, > > Seem's like you're trying to put people off FPL's for life. > They aren't that difficult to learn and you shouldn't under > estimate 13 year olds :-) > > As for the original question, I also have no idea how to access > OpenGL from Clean. (That doesn't mean it's impossible of course.) > You can do it in Haskell using HOpenGL.. > > http://www.haskell.org/HOpenGL/ > > Whether either language (Clean or Haskell) is good for gaming > probably depends on the game in question. I think they'd be good > for games of "intellect" (like chess,go etc). But if you need top > notch real time arcade quality 3D graphics and sound effects > for alien zapping style games they might not be the best choice. > > Regards > -- > Adrian Hey > > > > > _______________________________________________ > clean-list mailing list > clean-list@cs.kun.nl > http://www.cs.kun.nl/mailman/listinfo/clean-list > > From dvanarkel@mac.com Tue, 18 Feb 2003 00:44:37 +0100 Date: Tue, 18 Feb 2003 00:44:37 +0100 From: Diederik van Arkel dvanarkel@mac.com Subject: [clean-list] error message when compiling: short path ??? On Monday, February 17, 2003, at 09:49 PM, Spitsbroeders wrote: > Hi all, > I read about Clean in C'T, I became very interested because of the > very uncommon structure of this language. I installed the software and > tried some first steps, but I didn't even manage to compile the > "life-game" in the exaples section. I was confronted with the error > that a "short path" to the compiler was not found. My system is Win > 2k. I am only a programming newbie and I guess I have to try some > more, but I figure someone else's been going through this before and > might gimme a hint. > Thanks i.a. > Joost > Hi Joost, there are two possible causes I can think of offhand: 1) You navigated to the example project via the network name of your PC e.g. //Joost's PC/Clean/Examples/... The CleanIde currently has problems with this although I think this doesn't show itself until the code generation stage. 2) The environment settings got corrupted. If you didn't modify your setup from the distribution then if you look in Environments:Current Environment then you should see under the heading compiler:Tools/Clean System 2.0.2/Clean Compiler 2.0.2 and you should have a Clean Compiler 2.0.2.exe in the Clean/Tools/Clean System 2.0.2/ directory. If this doesn't help please mail me some further details of how you have setup your installation and we'll try to sort this out. Regards, Diederik van Arkel From costa@ufu.br Thu, 20 Feb 2003 12:06:26 -0300 Date: Thu, 20 Feb 2003 12:06:26 -0300 From: Eduardo Costa costa@ufu.br Subject: [clean-list] Alcimar-Paschoarelli's paper Dr. Alcimar's paper on the use of functional languages on signal processing and real time control (Functional Languages in Signal Porcessing Applied to Prosthetic Limb Control) was published in System Analysis Modelling Simulation, Vol. 42, Number 9, 09/2002, ISBN 0232-9298. By the way, Dr. Alcimar won the ASC- 2002 best paper award for another paper related to this one (it will be published soon, and I will let you know when it gets printed). The SAMS paper deals with a myoelectric control system for an upper-limb prosthesis. Dr. Alcimar used a special material called shape memory alloy (SMA) to act as actuator for the joints. SMA acts as an analogue of a biological muscle. The signal processing programs that recognizes the features of the myoelectric signals were written in Clean, C++, Mercury and Prolog (Ciao and GNU). The C++ programs were written by Dr. Jamil Salem Barbar. Nobody in the project is enthusiastic about Clean or functional programming. Even so, everybody agrees that (at least for signal processing) Clean: 1- is as fast as C. 2- uses less resources than the other languages, even C. Dr. Jamil, who performed the tests, do not know how to program in Clean, and don't like functional programming. However, he was amazed to see how stingy the Clean compiler is. 3- The debuging of the C and Matlab versions of the programs took months. The Clean prototype (using Zermelo-Frankel) worked right away and the Clean final version (iterative) was running after one week. I recommend that you people take a look at this interesting paper for more details. By the way, although I am in the list of authors, my contribuition was very small. In fact, the only thing I did was to suggest publishing the paper in the Functional Programming Journal, instead of sending it to a publication specialized in Modelling or in Bio-engineering. It turned out that my suggestion was discarded (I do not know the reason), but my name was kept in the list of authors. The signal processing algorithm used to retrieve features of the electro-myographics singal was designed by Dr. Paschoarelli, a mathematician. Eduardo Costa Este e-mail foi analisado pelo RAV AntiVirus no servidor doodle.dr.ufu.br da Universidade Federal de Uberlândia - Uberlândia - MG - Brasil From m.wittebrood@mailbox.kun.nl Fri, 21 Feb 2003 14:22:23 +0100 Date: Fri, 21 Feb 2003 14:22:23 +0100 From: Marco Kesseler m.wittebrood@mailbox.kun.nl Subject: [clean-list] Alcimar-Paschoarelli's paper >The C++ programs were written by Dr. Jamil Salem Barbar. >Nobody in the project is enthusiastic about Clean or functional >programming. Even so, everybody agrees that (at least for signal >processing) Clean: > >1- is as fast as C. >2- uses less resources than the other languages, even C. >Dr. Jamil, who performed the tests, do not know how to >program in Clean, and don't like functional programming. >However, he was amazed to see how stingy the Clean compiler is. Are these referring to the speed and resources of the compiler, or to those of the resulting programs? Are we talking about C or C++ here? >3- The debuging of the C and Matlab versions of the programs >took months. The Clean prototype (using Zermelo-Frankel) >worked right away and the Clean final version (iterative) >was running after one week. Now I am really wondering why nobody in the project is enthousiastic about Clean. What is there not to like? Is this largely a matter of taste? Did they start with C and then rewrote the program in Clean? What were the differences between the Clean prototype and the final version? (I don't know what iterative means here). >I recommend that you people take a look at this interesting paper >for more details. I am afraid that I will not be able to have a look at it, unless it is online somewhere. regards, Marco Kesseler From marrieda@lawyer.com Thu, 27 Feb 2003 19:44:35 -0500 Date: Thu, 27 Feb 2003 19:44:35 -0500 From: Mark Phillips marrieda@lawyer.com Subject: [clean-list] "code is data" and Clean Hi, One of the key advantages of LISP (as far as I can tell) is that its relatively simple (yet powerful) syntax means that LISP _code_ looks just like the _data_ it works on. Because of this, it is possible to manipulate LISP code in the same way, using the same powerful functions, that are used with data. This ability enables one to write even more powerful functions, and potentially more efficient ones. In LISP, code is just lists inside lists (a tree-like structure). Because of the simple (yet flexible) syntax for code, it makes writing code-manipulating functions quite easy to do. LISP proponents seem to argue that newer functional languages (like Haskell and Clean etc) are actually a step backwards because - with their more convoluted syntax - they've thrown away the ability to easily write code-manipulating-code. What I would like to know from the clean community (and perhaps developers) is: how much validity is there to this point? Is it a case of "Clean has thrown away the ability to easily write code manipulating code in exchange for some other goodies which we value more". If so, what are these other goodies and why are they worth more than code-manipulating-code ability. But I wonder whether Clean really has thrown away the code manipulating code capability. I have never programmed in Clean (I've used Haskell), but I did read something about Clean working with "computational graphs" or something like that. Ie, where LISP works with code as hierachical lists of lists (ie a tree), does Clean work with code as a graph? In which case Clean is potentially more powerful (and more computationally efficient) in this regard than LISP!! Because trees are a special case of a graph, and what's more, a tree with "isomorphic sub-trees" can sometimes be expressed more succinctly as a graph. Well, I don't know Clean (or LISP) well enough to be able to discern whether my ideas are on the right track or not. Any assistance with my thinking would be greatly appreciated. Thanks, Mark. -- __________________________________________________________ Sign-up for your own FREE Personalized E-mail at Mail.com http://www.mail.com/?sr=signup From karczma@info.unicaen.fr Fri, 28 Feb 2003 12:33:46 +0100 Date: Fri, 28 Feb 2003 12:33:46 +0100 From: Jerzy Karczmarczuk karczma@info.unicaen.fr Subject: [clean-list] "code is data" and Clean Mark Phillips wrote: > One of the key advantages of LISP (as far as I can tell) is > that its relatively simple (yet powerful) syntax means that > LISP _code_ looks just like the _data_ it works on. Because > of this, it is possible to manipulate LISP code in the same > way, using the same powerful functions, ... > In LISP, code is just lists inside lists (a tree-like > structure). Because of the simple (yet flexible) syntax > for code, it makes writing code-manipulating functions quite > easy to do. LISP proponents seem to argue that newer functional > languages (like Haskell and Clean etc) are actually a step > backwards because - with their more convoluted syntax - they've > thrown away the ability to easily write code-manipulating-code. Don't forget that modern Lisp and Scheme implementations *compile* their stuff. You are *not* speaking about the actual executable code, but about the *code source*, which for historical reasons is list based. True, in Lisp/Scheme you can easily write very powerful macros which transform the source code before compilation. This makes the language extensible: without changing the superficial syntax it is possible to write very complicated constructions. All that is possible only in an interpreted environment, or if a compiled program includes some substantial part of the compiler. It is possible with some versions of Scheme, but I cannot imagine the same simply done with Haskell or Clean. Clean and Haskell (and many other languages) have chosen a different conceptual approach, calling it "step backward" is not rational, actually for the last 15 years at least, I have never heard this claim from somebody *serious* (OK, let me keep my definition who is and who isn't serious...) We have pattern matching. We have strong typing. The last point means that if you wanted to be able to produce via macros a new code during the execution of the original, *your program* should include the type checker! In these languages there is a global analysis stage during the compilation, in Lisp this is absent. > What I would like to know from the clean community (and perhaps > developers) is: how much validity is there to this point? > > Is it a case of "Clean has thrown away the ability to easily > write code manipulating code in exchange for some other goodies > which we value more". If so, what are these other goodies and > why are they worth more than code-manipulating-code ability. I am not a language developer, just a user and a teacher. So, my answer should be completed by those who are 'insiders'. Still, I don't believe that in general those 'facilities' would do much good. What do you *REALLY* want? Give some examples. Do you want self-modifying codes? It was possible in Snobol. People were abhorred by it, the resulting programs were extremely difficult to debug. "Potentially more efficient" code? How? The abstractions such as closure construction are there already, and the efficiency of *lazy* programs is a very, very complex problem, needing a lot of global analysis. You mention that Clean is based on the graph reduction techniques. This - as far as I understand - is far from trying to give to the user program the possibility to tinker with the compiled code. It is far less readable than assembler... Well, my three euro-cents... Jerzy Karczmarczuk Caen, France From m.wittebrood@mailbox.kun.nl Fri, 28 Feb 2003 15:05:29 +0100 Date: Fri, 28 Feb 2003 15:05:29 +0100 From: Marco Kesseler m.wittebrood@mailbox.kun.nl Subject: [clean-list] "code is data" and Clean >Hi, > >One of the key advantages of LISP (as far as I can tell) is >that its relatively simple (yet powerful) syntax means that >LISP _code_ looks just like the _data_ it works on. Because >of this, it is possible to manipulate LISP code in the same >way, using the same powerful functions, that are used with >data. This ability enables one to write even more powerful >functions, and potentially more efficient ones. > >In LISP, code is just lists inside lists (a tree-like >structure). Because of the simple (yet flexible) syntax >for code, it makes writing code-manipulating functions quite >easy to do. LISP proponents seem to argue that newer functional >languages (like Haskell and Clean etc) are actually a step >backwards because - with their more convoluted syntax - they've >thrown away the ability to easily write code-manipulating-code. First of all: forgive me any misconceptions I might have about LISP. I know about LISP (syntax and semantics) and have read articles about it, but I have never used it for programming. Nevertheless: I think that some Clean proponents would argue that code manipulation is "not done". They would consider the need to do such a thing to be a weakness in a programming language like Clean. Not to say that LISP is "weak". Clean and LISP are strong in different areas, just like Perl and C are. Or Java and C++ for that matter. Things to consider: - There is little need to rewrite code in order to arrive at powerful functions. You can write powerful functions directly in Clean. The fact that this is highly appreciated in LISP does rather (in my humble opinion) demonstrate some sort of weakness in LISP's simple syntax. - Clean does not interpret expressions. It compiles them. And Clean is a strongly typed language. This means that many errors are caught at compile-time. In this respect Clean's design philosophy is fundamentally different from LISP's. - Clean has no standard "eval"-like function that interprets and evaluates some piece of data. So it is not _merely_ a matter of matching function syntax and data syntax. One could however, easily write an interpreter for any LISP-like (or Clean-like) language in Clean as well (but also see the next points, before you argue that this is not quite what LISP offers). - Rewriting expressions for the sake of efficiency is rather considered a task of the compiler. It is true that some of this is still somewhat a promise. I think that Clean (as Haskell) could do with better forms of compile-time evaluation of expressions (but that is being worked on as far as I know). Ultimately, optimising an interpreter for a given input program would deliver a compiled version of that program. Whether that goal is close is an entirely different matter. - I think that Clean would come closer to LISP if it started to incorporate some form of runtime (re)compilation of expressions. This seems somewhat related to the current efforts that are put in Dynamic types (also in the sense that the runtime infrastructure is getting into place). But note that just as the use of Dynamic types may introduce runtime typing errors, the use of runtime compilation would introduce runtime compiler errors, which seems somewhat opposite to catching errors as early as possible. >What I would like to know from the clean community (and perhaps >developers) is: how much validity is there to this point? > >Is it a case of "Clean has thrown away the ability to easily >write code manipulating code in exchange for some other goodies >which we value more". If so, what are these other goodies and >why are they worth more than code-manipulating-code ability. Personally, I am not sure I would call runtime code manipulation a "goody". >But I wonder whether Clean really has thrown away the code >manipulating code capability. I have never programmed in >Clean (I've used Haskell), but I did read something about >Clean working with "computational graphs" or something like >that. Ie, where LISP works with code as hierachical lists of >lists (ie a tree), does Clean work with code as a graph? In >which case Clean is potentially more powerful (and more >computationally efficient) in this regard than LISP!! Because >trees are a special case of a graph, and what's more, a tree >with "isomorphic sub-trees" can sometimes be expressed more >succinctly as a graph. Clean uses graph rewriting internally for its implementation, and its semantics are defined in terms of graph-rewriting. Clean's syntax is not. So Clean rewrite expressions aren't graphs. They are rules for manipulating them. And as such, they cannot manipulate themselves. >Well, I don't know Clean (or LISP) well enough to be able to >discern whether my ideas are on the right track or not. Any >assistance with my thinking would be greatly appreciated. I hope this helps (and makes sense). regards, Marco From rthappe@web.de Sat, 1 Mar 2003 19:21:29 +0100 (CET) Date: Sat, 1 Mar 2003 19:21:29 +0100 (CET) From: RT Happe rthappe@web.de Subject: [clean-list] "code is data" and Clean On Fri, 28 Feb 2003, Jerzy Karczmarczuk wrote: > > We have pattern matching. We have strong typing. The last point > means that if you wanted to be able to produce via macros a new > code during the execution of the original, *your program* should > include the type checker! In these languages there is a global > analysis stage during the compilation, in Lisp this is absent. Since macros are expanded during compilation (as you observed yourself) this isn't what macros do. A multi-stage compilation/analysis of the program composed of parts on various meta-levels --the most interesting being 0, 1, and ... omega-- should cut it. (I believe that Scheme 48 does some such thing. Cf. http://s48.org/.) Besides, complex applications that will have to be repaired or changed while running would certainly benefit from the compiler being available to the program (in the absence of a powerful development system). Of related interest: essays of Richard P.Gabriel, (former) leading light of the Lisp community, on the futility of the idea of perfect planning etc., e.g. ``Mob Software: The Erotic Life of Code'' at http://www.dreamsongs.com/Essays.html rthappe From rthappe@web.de Sat, 1 Mar 2003 18:35:50 +0100 (CET) Date: Sat, 1 Mar 2003 18:35:50 +0100 (CET) From: RT Happe rthappe@web.de Subject: [clean-list] "code is data" and Clean On Thu, 27 Feb 2003, Mark Phillips wrote: > One of the key advantages of LISP (as far as I can tell) is > that its relatively simple (yet powerful) syntax means that > LISP _code_ looks just like the _data_ it works on. Because It's appropriate to look at the components of this advantage. Some of these may be grafted on a modern functional language, or the effect may be achieved with other means. (0) a simple syntax for textual representations of data (1) a corresponding and well-supported built-in data-type (trees, basically) (2) i/o procedures translating the (textual) external into the (concrete) internal representation and v.v. (3) source code in the ``data-syntax'' from above (4) parse-trees represented --as far as the programmer is concerned-- by the concrete data-type from above (5) programmable syntax-extensions -- macros transforming the parse-tree of the input form with the full force of the programming language Items (0,1,2) are extremely useful, giving the principal advantage of XML without the pain. And they aren't even incompatible with modernity, although Clean's type system would complicate things a bit. This is mainly a question of library design. (A prefab parser construction kit would help with (2).) Items (3,4) ease meta-programming: writing partial evaluators, debuggers, etc. But that can be achieved with data abstraction (and perhaps less convenience), too, without exposing the concrete syntax of the language or the concrete data-type of the parse-tree. The logic language Goedel went that way. Item (5) enables syntactic abstraction. Macros are used to create special forms with a special evaluation rule (there's less need for that in a lazy language) and in general to embed problem-specific ``little languages'' into the host programming language, i.e. Lisp. This may be achieved with --> transformation rules (in the spirit of Scheme's SYNTAX-RULES) rather than with hand-coded expanders, but it will complicate the compilation process anyway. (I don't believe that macros preclude global program analysis, though.) rthappe From marrieda@lawyer.com Tue, 04 Mar 2003 00:51:36 -0500 Date: Tue, 04 Mar 2003 00:51:36 -0500 From: Mark Phillips marrieda@lawyer.com Subject: [clean-list] "code is data" and Clean Hi Jerzy, Thanks for your three euro cents :-) > Don't forget that modern Lisp and Scheme implementations *compile* > their stuff. You are *not* speaking about the actual executable > code, but about the *code source*, which for historical reasons > is list based. > True, in Lisp/Scheme you can easily write very powerful macros > which transform the source code before compilation. This makes > the language extensible: without changing the superficial syntax > it is possible to write very complicated constructions. > > All that is possible only in an interpreted environment, or if > a compiled program includes some substantial part of the compiler. > It is possible with some versions of Scheme, but I cannot imagine > the same simply done with Haskell or Clean. True it would make the executable large if part of a static executable, but why not make these extras dynamically loaded libraries? > Clean and Haskell (and many other languages) have chosen a different > conceptual approach, calling it "step backward" is not rational, > actually for the last 15 years at least, I have never heard this > claim from somebody *serious* (OK, let me keep my definition who > is and who isn't serious...) I have heard Lisp proponents effectively say just that. Some acknowlege that strong typing is a good thing, but that this should have been added to a Lisp-like language rather than losing the power of S-expressions and macros. > We have pattern matching. We have strong typing. The last point > means that if you wanted to be able to produce via macros a new > code during the execution of the original, *your program* should > include the type checker! In these languages there is a global > analysis stage during the compilation, in Lisp this is absent. >From what I've read, strong typing seems more valuable than pattern matching... There seems to be a belief out there that strong typing could have been made available without losing something like S-expressions and macros. I don't know how realistic this is. Perhaps the program (or a dynamic library) should provide a type checker. Perhaps there is a time and place for type checking and a time and place for bypassing it?? > I am not a language developer, just a user and a teacher. So, > my answer should be completed by those who are 'insiders'. Still, > I don't believe that in general those 'facilities' would do > much good. What do you *REALLY* want? Give some examples. Sadly I can't yet - I currently have very limited experience in Lisp. However I do read Lisp proponents arguing that macros and S-expressions really do give them something important that no other language really does. I wonder whether they have a point. I also wonder whether they're wrong. That is what I am trying to ascertain. > Do > you want self-modifying codes? It was possible in Snobol. People > were abhorred by it, the resulting programs were extremely > difficult to debug. I have long heard the mantra: "self modifying code is bad". I am not convinced however. Sure the behaviour is much more complex and potentially more dangerous, but perhaps that simply means it should be controlled using more sophisticated means. Perhaps people gave up on self modifying code before they had properly learned how to control it? Cheers, Mark. -- __________________________________________________________ Sign-up for your own FREE Personalized E-mail at Mail.com http://www.mail.com/?sr=signup From marrieda@lawyer.com Tue, 04 Mar 2003 01:12:49 -0500 Date: Tue, 04 Mar 2003 01:12:49 -0500 From: Mark Phillips marrieda@lawyer.com Subject: [clean-list] "code is data" and Clean Hi, Thanks for your thoughtful comments. > > One of the key advantages of LISP (as far as I can tell) is > > that its relatively simple (yet powerful) syntax means that > > LISP _code_ looks just like the _data_ it works on. Because > > It's appropriate to look at the components of this advantage. Some of > these may be grafted on a modern functional language, or the effect may be > achieved with other means. Thanks for the analysis below. I am curious about how you see the programming language landscape however. Do you think that the approach of Clean is fundamentally incompatible with the approach of Lisp, and the advantages of Clean (etc) outweigh those of Lisp so we should use Clean (or Haskell etc) and add on some of the extra functionality of Lisp as best we can? Or perhaps you think the best of both worlds could have been combined, but weren't, so let's add on extra functionality as best we can? Or perhaps your ideas are different from either of these. Just curious. > (0) a simple syntax for textual representations of data > (1) a corresponding and well-supported built-in data-type (trees, > basically) > (2) i/o procedures translating the (textual) external into the (concrete) > internal representation and v.v. > > (3) source code in the ``data-syntax'' from above > (4) parse-trees represented --as far as the programmer is concerned-- by > the concrete data-type from above > > (5) programmable syntax-extensions -- macros transforming the parse-tree > of the input form with the full force of the programming language > > Items (0,1,2) are extremely useful, giving the principal advantage of XML > without the pain. And they aren't even incompatible with modernity, > although Clean's type system would complicate things a bit. This is > mainly a question of library design. (A prefab parser construction kit > would help with (2).) > > Items (3,4) ease meta-programming: writing partial evaluators, debuggers, > etc. But that can be achieved with data abstraction (and perhaps less > convenience), too, without exposing the concrete syntax of the language or > the concrete data-type of the parse-tree. The logic language Goedel went > that way. Could you please expand on what you mean by this - thanks. Do you feel the exposing of concrete syntax and parse-tree data-type is not so important? > Item (5) enables syntactic abstraction. Macros are used to create special > forms with a special evaluation rule (there's less need for that in a lazy > language) and in general to embed problem-specific ``little languages'' > into the host programming language, i.e. Lisp. This may be achieved with > --> transformation rules (in the spirit > of Scheme's SYNTAX-RULES) rather than with hand-coded expanders, but it > will complicate the compilation process anyway. (I don't believe that > macros preclude global program analysis, though.) > > rthappe > > > > > _______________________________________________ > clean-list mailing list > clean-list@cs.kun.nl > http://www.cs.kun.nl/mailman/listinfo/clean-list -- __________________________________________________________ Sign-up for your own FREE Personalized E-mail at Mail.com http://www.mail.com/?sr=signup From marrieda@lawyer.com Tue, 04 Mar 2003 00:07:44 -0500 Date: Tue, 04 Mar 2003 00:07:44 -0500 From: Mark Phillips marrieda@lawyer.com Subject: [clean-list] "code is data" and Clean Hi Marco, Thanks for your thoughts on the questions I raise. I am trying to get a better grasp of what is and is not important in a programming language and this discussion is very useful. > I think that some Clean proponents would argue that code manipulation > is "not done". They would consider the need to do such a thing to be > a weakness in a programming language like Clean. Not to say that LISP > is "weak". Clean and LISP are strong in different areas, just like > Perl and C are. Or Java and C++ for that matter. Things to consider: Lisp proponents argue that code manipulation ability is a strength. They say it means one is not limited to the programming ideas in vogue when the language was invented. Yes I have heard the argument "there is no 'best' language, just different languages with different strengths". There is an element of truth to this, yet I do believe there are some languages which are generally better than other languages. However I have not come to firm conclusions about what constructs are most important in a language. > - There is little need to rewrite code in order to arrive at powerful > functions. You can write powerful functions directly in Clean. The > fact that this is highly appreciated in LISP does rather (in my > humble opinion) demonstrate some sort of weakness in LISP's simple > syntax. Perhaps you are right. But Lisp proponents seem to argue that you are bound to come across an example which Clean doesn't handle at all well - and then you are stuck - you pay a high price. Lisp people argue that S-expressions and macros mean that you avoid paying this high price. Sometimes you pay a low price, eg when something can be expressed more cleanly in clean - but this price can be made small through the use of macros. > - Clean does not interpret expressions. It compiles them. And Clean > is a strongly typed language. This means that many errors are caught > at compile-time. In this respect Clean's design philosophy is > fundamentally different from LISP's. I like the idea of strong typing. But why not add strong typing to Lisp? Why not add the advantages of Clean to a Lisp like language? Perhaps there are good reasons - I don't know them yet however. > > - Clean has no standard "eval"-like function that interprets and > evaluates some piece of data. So it is not _merely_ a matter of > matching function syntax and data syntax. One could however, easily > write an interpreter for any LISP-like (or Clean-like) language in > Clean as well (but also see the next points, before you argue that > this is not quite what LISP offers). > > - Rewriting expressions for the sake of efficiency is rather > considered a task of the compiler. It is true that some of this is > still somewhat a promise. I think that Clean (as Haskell) could do > with better forms of compile-time evaluation of expressions (but that > is being worked on as far as I know). Ultimately, optimising an > interpreter for a given input program would deliver a compiled > version of that program. Whether that goal is close is an entirely > different matter. > > - I think that Clean would come closer to LISP if it started to > incorporate some form of runtime (re)compilation of expressions. This > seems somewhat related to the current efforts that are put in Dynamic > types (also in the sense that the runtime infrastructure is getting > into place). But note that just as the use of Dynamic types may > introduce runtime typing errors, the use of runtime compilation would > introduce runtime compiler errors, which seems somewhat opposite to > catching errors as early as possible. I am curious to know more about what Clean's dynamics really are and really do. How close do they come to Lisp's dynamic nature? I agree that catching errors early is good... unless this requirement prevents you programming more powerfully. Why not do the first where possible and the second elsewhere? > Clean uses graph rewriting internally for its implementation, and its > semantics are defined in terms of graph-rewriting. Clean's syntax is > not. So Clean rewrite expressions aren't graphs. They are rules for > manipulating them. And as such, they cannot manipulate themselves. I wonder whether it would have been possible for Clean to be designed with the graphs explicit? And if so, I wonder why they chose not to. Cheers, Mark. -- __________________________________________________________ Sign-up for your own FREE Personalized E-mail at Mail.com http://www.mail.com/?sr=signup From rthappe@web.de Tue, 4 Mar 2003 22:19:59 +0100 (CET) Date: Tue, 4 Mar 2003 22:19:59 +0100 (CET) From: RT Happe rthappe@web.de Subject: [clean-list] "code is data" and Clean On Tue, 4 Mar 2003, Mark Phillips wrote: > Thanks for the analysis below. I am curious about how you see > the programming language landscape however. Do you think that > the approach of Clean is fundamentally incompatible with the > approach of Lisp, and the advantages of Clean (etc) outweigh Being fairly incompetent and inexperienced, I'd better keep my thoughts to myself. (First principles aren't a good sybstitute for experience.) Briefly, I believe a syntactically extensible language featuring static analysis (type inference and all that) would be feasible and useful, but more likely descend from Scheme than from Clean. E.g. I heard PLT Scheme offers ``soft typers'' as analytic tools (but wisely keeps the runtime type information, I suppose). > > Items (3,4) ease meta-programming: writing partial evaluators, debuggers, > > etc. But that can be achieved with data abstraction (and perhaps less > > convenience), too, without exposing the concrete syntax of the language or > > the concrete data-type of the parse-tree. The logic language Goedel went > > that way. > > Could you please expand on what you mean by this - thanks. Do you > feel the exposing of concrete syntax and parse-tree data-type is > not so important? If your goal is manipulation of (textual) Clean programs (rather than extending Clean), a library implementing abstract data types (`module', `type declaration', `start graph', ...) with the necessary host of operations (read/write program, match terms, ...) would do the job, too. [ Prolog is very much like Lisp w.r.t. the relation of source code and data. In particular, Prolog represents facts and rules (subprograms) by Prolog structures aka terms. Its descendant Goedel takes the ADT approach instead: it offers library modules for converting the textual form of programs into/from the opaque representation, and for operating on the representants. ] rthappe PS on the merits of syntactic extensibility Those who wonder when and why powerful macros may be useful may want to have a look at some examples: Simple but non-trivial examples from the ``Scheme Requests for Implementation'' http://srfi.schemers.org/final-srfis.html SRFI 2 -- AND-LET*: an AND with local bindings (...) SRFI 5 -- A compatible let form with signatures and rest arguments SRFI 9 -- Defining Record Types The Scheme Shell, a Unix shell embedded in Scheme, makes heavy use of macros (process forms, awk special form, ...), but typically provides both the procedural substrate and the convenient macroidal interface built on top. The reference manual and the design paper are in the [docu] section of http://www.scsh.net/. Paul Graham -- On Lisp; http://www.paulgraham.com/onlisp.html preaches and demonstrates the ``bottom-up'' way of evolving the language towards the application; a bit over the top at times. On ``metalinguistic abstraction'' in general (with the help of interpreters here, not macros): Abelson/Sussman -- Structure and Interpretation of Computer Programs http://mitpress.mit.edu/sicp/ http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-25.html#%_chap_4 From alanh@dcs.kcl.ac.uk Wed, 5 Mar 2003 13:57:36 +0000 (GMT) Date: Wed, 5 Mar 2003 13:57:36 +0000 (GMT) From: alanh@dcs.kcl.ac.uk alanh@dcs.kcl.ac.uk Subject: [clean-list] "code is data" and Clean On Wednesday 5-3-03, R T Happe wrote > > PS on the merits of syntactic extensibility > > Those who wonder when and why powerful macros may be useful may want to > have a look at some examples: Here are some more references on adventurous forms of programming which would probably not get past a decent type system: Luca Cardelli A polymorphic calculus with Type: Type DEC Systems Research Center, Palo Alto, U.S.A. January 1986 Brian Cantwell Smith Reflection and Semantics in LISP Report No. CSLI-84-8 Center for the Study of Language and Information, Stanford, U.S.A. Not many programming languages have facilites which help coding of the ideas in these references. LISP with its "eval" is one of the few. The designers of Clean probably never meant it to be used for such purposes. Alan Hutchinson Department of Computer Science King's College London From igouy@yahoo.com Wed, 5 Mar 2003 10:07:14 -0800 (PST) Date: Wed, 5 Mar 2003 10:07:14 -0800 (PST) From: isaac gouy igouy@yahoo.com Subject: [clean-list] How to compile clean from the command line? This question came up on this list some time ago, and it seemed that the intention was that it would be addressed with Clean 2. Is there a way to use the compiler linker from MS Windows command line? (Although I like IDEs, it's nice to script and automate) best wishes, Isaac __________________________________________________ Do you Yahoo!? Yahoo! Tax Center - forms, calculators, tips, more http://taxes.yahoo.com/ From dvanarkel@mac.com Thu, 6 Mar 2003 00:31:31 +0100 Date: Thu, 6 Mar 2003 00:31:31 +0100 From: Diederik van Arkel dvanarkel@mac.com Subject: [clean-list] How to compile clean from the command line? On Wednesday, March 5, 2003, at 07:07 PM, isaac gouy wrote: > This question came up on this list some time ago, and > it seemed that the intention was that it would be > addressed with Clean 2. > > Is there a way to use the compiler linker from MS > Windows command line? > (Although I like IDEs, it's nice to script and > automate) > > best wishes, Isaac > Hi Isaac, rather than directly calling the compiler, code generator, and linker I'd suggest using the non-interactive mode of the ide. I can't remember right now if these are documented in the ide manual. If not I'll write them up in the morning. This lets you tell the ide to bring a project up to date without actually bringing up the gui. Regards, Diederik van Arkel From diederik@cs.kun.nl Thu, 06 Mar 2003 09:28:14 +0100 Date: Thu, 06 Mar 2003 09:28:14 +0100 From: Diederik van Arkel diederik@cs.kun.nl Subject: [clean-list] How to compile clean from the command line? At 12:31 AM 3/6/2003 +0100, I wrote: >On Wednesday, March 5, 2003, at 07:07 PM, isaac gouy wrote: > >>This question came up on this list some time ago, and >>it seemed that the intention was that it would be >>addressed with Clean 2. >> >>Is there a way to use the compiler linker from MS >>Windows command line? >>(Although I like IDEs, it's nice to script and >>automate) >> >>best wishes, Isaac > >Hi Isaac, > >rather than directly calling the compiler, code generator, >and linker I'd suggest using the non-interactive mode of the >ide. I can't remember right now if these are documented in the >ide manual. If not I'll write them up in the morning. This lets >you tell the ide to bring a project up to date without actually >bringing up the gui. > >Regards, > >Diederik van Arkel I don't see the documentation in the ide manual so: E:\Ronny\Develop\CleanSystem\CleanIDE.exe -h 25M --batch-force-build %1 E:\Ronny\Develop\CleanSystem\CleanIDE.exe -h 25M --batch-build %1 are the two variants you can use. The -h flag allows you to set the heap size for the ide in case it needs to be increased. %1 is where you provide the full path to your project. Regards, Diederik van Arkel From igouy@yahoo.com Thu, 6 Mar 2003 13:14:15 -0800 (PST) Date: Thu, 6 Mar 2003 13:14:15 -0800 (PST) From: isaac gouy igouy@yahoo.com Subject: [clean-list] How to compile clean from the command line? Just to emphasise something I missed at first: CleanIDE.exe --batch-build This works nicely, thank you. > I don't see the documentation in the ide manual so: > > E:\Ronny\Develop\CleanSystem\CleanIDE.exe -h 25M > --batch-force-build %1 > E:\Ronny\Develop\CleanSystem\CleanIDE.exe -h 25M > --batch-build %1 > > are the two variants you can use. The -h flag allows > you to set the heap size > for the ide in case it needs to be increased. %1 is > where you provide the full > path to your project. __________________________________________________ Do you Yahoo!? Yahoo! Tax Center - forms, calculators, tips, more http://taxes.yahoo.com/ From igouy@yahoo.com Mon, 10 Mar 2003 20:38:47 -0800 (PST) Date: Mon, 10 Mar 2003 20:38:47 -0800 (PST) From: isaac gouy igouy@yahoo.com Subject: [clean-list] newbie: simple console IO and 65536 Puzzled by the behaviour of this simple console IO program (on Windows XP). After echoing back an inputline, 65536 appears on the console? How do I avoid this behaviour? --------------- module echoline import StdEnv Start:: *World -> *World Start world # (console, world) = stdio world (ln, console) = freadline console console = fwrites ln console (ok, world) = fclose console world | not ok = abort "problem!" = world --------------- I:\Clean>echoline -con input line input line 65536 --------------- __________________________________________________ Do you Yahoo!? Yahoo! Web Hosting - establish your business online http://webhosting.yahoo.com From fzuurbie@inter.nl.net Tue, 11 Mar 2003 08:04:31 UT Date: Tue, 11 Mar 2003 08:04:31 UT From: fzuurbie@inter.nl.net fzuurbie@inter.nl.net Subject: [clean-list] newbie: simple console IO and 65536 This is a multi-part message in MIME format. --_----------=_1047369871258374 Content-Disposition: inline Content-Length: 1655 Content-Transfer-Encoding: binary Content-Type: text/plain Isaac wrote: > Puzzled by the behaviour of this simple console IO > program (on Windows XP). After echoing back an > inputline, 65536 appears on the console? How do I > avoid this behaviour? > > --------------- > module echoline > import StdEnv > > Start:: *World -> *World > Start world > # (console, world) = stdio world > (ln, console) = freadline console > console = fwrites ln console > (ok, world) = fclose console world > | not ok = abort "problem!" > = world > --------------- > I:\Clean>echoline -con > input line > input line > 65536 Usually it is enough to set one of the Application options to 'no console'. Even in your case, where you use the console, this is the first step. A minor problem is then that you won't even have the time to watch what the program echos: the program will exit immediately after it has displayed the echoed line and remove the console window. To remedy this, you can add an extra line of code as follows, which lets the program wait for another CRLF before exiting. Okay, this is a remedy. I am as puzzled as you are why the strange number is displayed in the first place. It is the standard way a program exits though. It certainly isn't a programming error on your part. Regards Erik Zuurbier module echoline import StdEnv Start:: *World -> *World Start world # (console, world) = stdio world (ln, console) = freadline console console = fwrites ln console (ln, console) = freadline console // added line (ok, world) = fclose console world | not ok = abort "problem!" = world --_----------=_1047369871258374-- From t.zielonka@students.mimuw.edu.pl Tue, 11 Mar 2003 09:59:45 +0100 Date: Tue, 11 Mar 2003 09:59:45 +0100 From: Tomasz Zielonka t.zielonka@students.mimuw.edu.pl Subject: [clean-list] newbie: simple console IO and 65536 On Mon, Mar 10, 2003 at 08:38:47PM -0800, isaac gouy wrote: > Puzzled by the behaviour of this simple console IO > program (on Windows XP). After echoing back an > inputline, 65536 appears on the console? How do I > avoid this behaviour? On Linux I used -nr compiler (clm) option to achieve this, but I don't know how to turn it on on Windows. Maybe search for something like "No Result" option in IDE. Best regards, Tom -- .signature: Too many levels of symbolic links From peter88@cs.kun.nl Tue, 11 Mar 2003 12:05:10 +0100 Date: Tue, 11 Mar 2003 12:05:10 +0100 From: Peter Achten peter88@cs.kun.nl Subject: [clean-list] newbie: simple console IO and 65536 At 20:38 10-3-03 -0800, Isaac Gouy wrote: >Puzzled by the behaviour of this simple console IO >program (on Windows XP). After echoing back an >inputline, 65536 appears on the console? How do I >avoid this behaviour? > >--------------- >module echoline >import StdEnv > >Start:: *World -> *World >Start world > # (console, world) = stdio world > (ln, console) = freadline console > console = fwrites ln console > (ok, world) = fclose console world > | not ok = abort "problem!" > = world >--------------- >I:\Clean>echoline -con >input line >input line >65536 >--------------- Other people have already commented on how to get rid of this magic number, allow me to explain why you get the number in the first place. Every Clean program attempts to print the result of the Start rule. In this case, the Start rule expects a value of type World and returns a new value of type World. The type World represents any external resource that your program might want to manipulate (such as the console in this program). The World happens to be implemented as an integer internally. In older Clean versions we used the bits of this integer to mark the use of particular subenvironments (external resources). A nicer representation would probably be something like "World" or even nothing at all as the world is already (t)here. Hope this helps, Peter Achten From m.wittebrood@mailbox.kun.nl Tue, 11 Mar 2003 22:40:30 +0100 Date: Tue, 11 Mar 2003 22:40:30 +0100 From: Marco Kesseler m.wittebrood@mailbox.kun.nl Subject: [clean-list] Wish List Update Dear Clean users, FYI: the Clean wish list has been updated. See: http://www.cs.kun.nl/~clean/wish/main.html main changes: - the list has been split into a number of pages, in an attempt to make the main page more concise. - more wishes have been added, mostly after suggestions of clean-list readers (thanks!). regards, Marco From igouy@yahoo.com Tue, 11 Mar 2003 10:00:25 -0800 (PST) Date: Tue, 11 Mar 2003 10:00:25 -0800 (PST) From: isaac gouy igouy@yahoo.com Subject: [clean-list] newbie: simple console IO and 65536 > Usually it is enough to set one of the Application > options to 'no console'... the program will exit > immediately after it has displayed the echoed line > and remove the console window. With 'no console' the program seems to be exiting *without* waiting for input from the console (freadline)? > A minor problem is then that you won't even have > the time to watch what the program echos... > To remedy this, you can add an extra line of code as > follows, which lets the program wait for another > CRLF before exiting. My expectation from "commandline programs" written in other languages, is that they will exit. My expectation is that I will run such programs from an OS command window (rather than from within an IDE) - so it's not something I experience as a problem. best wishes, Isaac __________________________________________________ Do you Yahoo!? Yahoo! Web Hosting - establish your business online http://webhosting.yahoo.com From igouy@yahoo.com Tue, 11 Mar 2003 09:58:55 -0800 (PST) Date: Tue, 11 Mar 2003 09:58:55 -0800 (PST) From: isaac gouy igouy@yahoo.com Subject: [clean-list] newbie: simple console IO and 65536 > Start rule expects a value of type World and returns > a new value of type World... > A nicer representation would probably be something > like "World" or even nothing at all as the world is > already (t)here. Peter, thanks for the explanation. My guess was that the magic number was akin to a file handle for stdio - so you clarified that slight misunderstanding. Showing "World" would make concrete that the Start rule was indeed returning a value of type world. On the other hand, as a practical matter, I'm just trying to control what is displayed on the console, so not displaying 65536 or World would be a better solution for me ;-) best wishes, Isaac __________________________________________________ Do you Yahoo!? Yahoo! Web Hosting - establish your business online http://webhosting.yahoo.com From m.verver@student.utwente.nl Wed, 12 Mar 2003 14:09:33 +0100 Date: Wed, 12 Mar 2003 14:09:33 +0100 From: Maks Verver m.verver@student.utwente.nl Subject: [clean-list] newbie: simple console IO and 65536 Hi Isaac, I usually work around this by returning something other than world. For example: Start:: *World -> String Start world # (console, world) = stdio world (ln, console) = freadline console console = fwrites ln console (ok, world) = fclose console world | not ok = abort "problem!" = "" This works because the empty string is invisible if the console is set to "basic values only". However, I think is a rather inappropriate hack. It would be much nicer if either World objects would not be printed at all (since their integer representation isn't very useful), or there would be an option to turn of printing the result value. Either way, it would be possible to write a number of potential Start rules and select the right one at run-time, or execute several functions in sequence (using the seq-function on a list of functions of type *World->*World, for example). This is possible now, but only with a work-round like above. Kind regards, Maks Verver. > -----Original Message----- > From: clean-list-admin@cs.kun.nl > [mailto:clean-list-admin@cs.kun.nl] On Behalf Of isaac gouy > Sent: dinsdag 11 maart 2003 5:39 > To: clean-list@cs.kun.nl > Subject: [clean-list] newbie: simple console IO and 65536 > > > Puzzled by the behaviour of this simple console IO > program (on Windows XP). After echoing back an > inputline, 65536 appears on the console? How do I > avoid this behaviour? > > --------------- > module echoline > import StdEnv > > Start:: *World -> *World > Start world > # (console, world) = stdio world > (ln, console) = freadline console > console = fwrites ln console > (ok, world) = fclose console world > | not ok = abort "problem!" > = world > --------------- > I:\Clean>echoline -con > input line > input line > 65536 > --------------- > From igouy@yahoo.com Tue, 18 Mar 2003 12:39:04 -0800 (PST) Date: Tue, 18 Mar 2003 12:39:04 -0800 (PST) From: isaac gouy igouy@yahoo.com Subject: [clean-list] eof for console input Trying to use file redirection with windows xp, like- >testprog -con < inputfile.txt I haven't been able to figure out how to check for eof when using freadline with the console. As an extreme example, if inputfile.txt is an empty file, this program just gives the message "Heap full." Start:: *World -> String Start world # (console, world) = stdio world # (line, console) = freadline console # (ok, world) = fclose console world = line So 2 questions: - what's happening to use up heap space? - as sfend and fend cannot be used with the console, how can I check for eof? best wishes, Isaac __________________________________________________ Do you Yahoo!? Yahoo! Platinum - Watch CBS' NCAA March Madness, live on your desktop! http://platinum.yahoo.com From EZuurbier@Abz.nl Wed, 19 Mar 2003 15:00:08 +0100 Date: Wed, 19 Mar 2003 15:00:08 +0100 From: Erik Zuurbier EZuurbier@Abz.nl Subject: [clean-list] Re: eof for console input This message is in MIME format. Since your mail reader does not understand this format, some or all of this message may not be legible. ------_=_NextPart_001_01C2EE1F.D9D0ECA0 Content-Type: text/plain Isaac wrote: >Start:: *World -> String >Start world > # (console, world) = stdio world > # (line, console) = freadline console > # (ok, world) = fclose console world > = line First note that the penultimate line is dead code. >So 2 questions: >- what's happening to use up heap space? >- as sfend and fend cannot be used with the console, >how can I check for eof? I can only answer the second question: there is never ever an end-of-file on the console. The program can always read more from the console as long as it is open. If you don't type in anything when the program is waiting for it, that does not mean that an end-of-file is reached. If you really really want to do an eof-check on the console, use the following code: fendConsole :: *File -> (Bool,*File) fendConsole console = (False,console;-) If you think redirecting a file to play the role of the console DOES create a need for an eof-check in a console, well too bad: Clean's designers probably had not foreseen redirections. Use fopen instead of stdio. If you want to be able to abstract out the file type (physical file or console) apply for a redesign of the StdFile module. I can imagine that a redesign may bring more benefits. For instance if type classes were used, I can imagine that the typechecker could discriminate read-files from write-files, data-files from text-files etc. moving various run time errors (e.g. writing to a read-file) to the realm of compile time checks. Regards Erik Zuurbier best wishes, Isaac ------_=_NextPart_001_01C2EE1F.D9D0ECA0 Content-Type: text/html Re: eof for console input

Isaac wrote:
>Start:: *World -> String
>Start world
>       # (console, world) = stdio world
>       # (line, console) = freadline console
>       # (ok, world) = fclose console world
>       = line
First note that the penultimate line is dead code.
>So 2 questions:
>- what's happening to use up heap space?
>- as sfend and fend cannot be used with the console,
>how can I check for eof?

I can only answer the second question: there is never ever an end-of-file on the console.
The program can always read more from the console as long as it is open.
If you don't type in anything when the program is waiting for it, that does not mean
that an end-of-file is reached. If you really really want to do an eof-check on the console,
use the following code:

fendConsole :: *File -> (Bool,*File)
fendConsole console = (False,console;-)

If you think redirecting a file to play the role of the console DOES create a need for
an eof-check in a console, well too bad: Clean's designers probably had not foreseen
redirections. Use fopen instead of stdio. If you want to be able to abstract out the file type
(physical file or console) apply for a redesign of the StdFile module. I can imagine that
a redesign may bring more benefits. For instance if type classes were used, I can imagine
that the typechecker could discriminate read-files from write-files, data-files from text-files
etc. moving various run time errors (e.g. writing to a read-file) to the realm of compile time
checks.

Regards Erik Zuurbier


 best wishes, Isaac

------_=_NextPart_001_01C2EE1F.D9D0ECA0-- From shiv@ece.ucsb.edu Wed, 19 Mar 2003 09:11:38 -0800 Date: Wed, 19 Mar 2003 09:11:38 -0800 From: Shivkumar Chandrasekaran shiv@ece.ucsb.edu Subject: [clean-list] Mac OS X? Are there any plans for a Mac OS X implementation of Clean? --shiv-- From igouy@yahoo.com Wed, 19 Mar 2003 11:51:08 -0800 (PST) Date: Wed, 19 Mar 2003 11:51:08 -0800 (PST) From: isaac gouy igouy@yahoo.com Subject: [clean-list] Re: eof for console input > fendConsole :: *File -> (Bool,*File) > fendConsole console = (False,console;-) ho ho > If you think redirecting a file to play the role of > the console DOES create a need for an eof-check in > a console, well too bad Indeed it is too bad. It's a shame to be prevented from using such an interesting language, by such an uninteresting problem. __________________________________________________ Do you Yahoo!? Yahoo! Platinum - Watch CBS' NCAA March Madness, live on your desktop! http://platinum.yahoo.com From coelacanth@blueyonder.co.uk Thu, 20 Mar 2003 12:18:18 -0000 Date: Thu, 20 Mar 2003 12:18:18 -0000 From: Stephan Haugh coelacanth@blueyonder.co.uk Subject: [clean-list] okNotice crashes This is a multi-part message in MIME format. ------=_NextPart_000_0016_01C2EEDA.CA81A350 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Hi all, I am modifying the WinEditor project (from the Clean GUI source). In the = file Editor\EdClient.icl I am calling (appEnv (okNotice [result])) along the examples of CopyClipboard and so on. result is a String. It = often works as expected, but every now and again it crashes, gives me a = blank DOS window and dies on me.=20 Did this happen to anybody before? Is it okNotice? Or is it in the = function that generates result? Cheers, Stephan ------=_NextPart_000_0016_01C2EEDA.CA81A350 Content-Type: text/html; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable
Hi all,
I am modifying the WinEditor project = (from the=20 Clean GUI source). In the file Editor\EdClient.icl I am = calling
 
(appEnv (okNotice = [result]))
 
along the examples of CopyClipboard and = so on.=20 result is a String. It often works as expected, but every now and again = it=20 crashes, gives me a blank DOS window and dies on me.
 
Did this happen to anybody before? Is = it okNotice?=20 Or is it in the function that generates result?
 
Cheers,
Stephan
------=_NextPart_000_0016_01C2EEDA.CA81A350-- From diederik@cs.kun.nl Thu, 20 Mar 2003 14:15:28 +0100 Date: Thu, 20 Mar 2003 14:15:28 +0100 From: Diederik van Arkel diederik@cs.kun.nl Subject: [clean-list] okNotice crashes At 12:18 PM 3/20/2003 +0000, you wrote: >Hi all, >I am modifying the WinEditor project (from the Clean GUI source). In the >file Editor\EdClient.icl I am calling > >(appEnv (okNotice [result])) > >along the examples of CopyClipboard and so on. result is a String. It >often works as expected, but every now and again it crashes, gives me a >blank DOS window and dies on me. > >Did this happen to anybody before? Is it okNotice? Or is it in the >function that generates result? > >Cheers, >Stephan Hi Stephan, I'd suggest turning on stack checks and stack traces in the project options and look what kind of stack trace you get when it crashes. If that doesn't give you a clue you might want to post some of the code you are using. Regards, Diederik van Arkel From shivers@cc.gatech.edu Tue, 25 Mar 2003 01:22:30 -0500 (EST) Date: Tue, 25 Mar 2003 01:22:30 -0500 (EST) From: Olin Shivers shivers@cc.gatech.edu Subject: [clean-list] FINAL CALL for papers: ICFP 2003 deadline is Saturday The submission deadline for ICFP -- the International Conference on Functional Programming -- is coming up soon: this Saturday, March 29. The 2003 ICFP will be in Uppsala, Sweden on August 25-29, in conjunction with PPDP (Principles and Practice of Declarative Programming). Please take a moment to read the "call for papers" I've appended below, and see if you have a topic or result you would like to submit to the program committee. See you in Sweden. -Olin Shivers program chairman =============================================================================== Eighth Annual ACM SIGPLAN International Conference on Functional Programming ICFP 2003 Call for Papers (Revised 2003/2/5) Affiliated with PLI 2003 August 25-29, 2003 Uppsala, Sweden http://www-users.cs.york.ac.uk/~colin/icfp2003.html http://www.cc.gatech.edu/icfp03/cfp.html ------------------------------------------------------------------------------- * Important dates ----------------- Submission deadline 18:00 EST 29 March, 2003 (Saturday) Notification of acceptance rejection 19 May, 2003 Final paper due 16 June, 2003 Conference 25-29 August, 2003 * Scope ------- ICFP 2003 seeks original papers on the full spectrum of the art, science, and practice of functional programming. The conference invites submissions on all topics ranging from principles to practice, from foundations to features, and from abstraction to application. The scope covers all languages that encourage programming with functions, including both purely applicative and imperative languages, as well as languages that support objects and concurrency. Topics of interest include, but are not limited to, the following: Foundations formal semantics, lambda calculus, type theory, monads, continuations, control, state, effects. Design Algorithms and data structures, modules and type systems, concurrency and distribution, components and composition, relations to object-oriented and logic programming, multiparadigm programming. Implementation abstract machines, compile-time and run-time optimization, just-in-time compilers, memory management. Interfaces to foreign functions, services, components and low-level machine resources. Transformation and analysis abstract interpretation, partial evaluation, program transformation, theorem proving, specification and verification. Software development techniques for functional programming design patterns, specification, verification and validation, debugging, test generation, tracing and profiling. Applications and domain-specific languages systems programming, scientific and numerical computing, symbolic computing and artificial intelligence, systems programming, databases, graphical user interfaces, multimedia programming, application scripting, system administration, distributed-systems construction, web programming. Practice and experience functional programming in education and industry, ramifications on other paradigms and computing disciplines. Functional pearls elegant, instructive examples of functional programming. Papers in the latter three categories need not necessarily report original research results; they may instead, for example, report practical experience that will be useful to others, re-usable programming idioms, or elegant new ways of approaching a problem. The key criterion for such a paper is that it makes a contribution from which other practitioners can benefit. It is not enough simply to describe a program! * Submission guidelines ----------------------- Due date & time: Submissions must be filed at the web site by 18:00 EST on Saturday 29 March. Some convenient equivalents to 18:00 EST are New York: 6:00 PM = 18h00 San Francisco: 3:00 PM = 15h00 Chicago: 5:00 PM = 17h00 Paris: Midnight Hong Kong: 7:00 AM (30 March) UTC: 2300 For other time-zones/locations, see http://www.timeanddate.com/worldclock/fixedtime.html Submission URL: http://www.cc.gatech.edu/icfp03/submit Authors should submit a 100-200 word abstract and a full paper by 23:00 Universal Coordinated Time on Saturday, 29 March, 2003. Submissions should be no more than 12 pages (including bibliography and appendices) in standard ACM conference format: two columns, nine-point font on a ten-point baseline, with pages 20pc (3.33in) wide and 54pc (9in) tall, with a column gutter of 2pc (0.33in). Detailed formatting guidelines are available at http://www.acm.org/sigs/pubs/proceed/template.html, along with formatting templates or style files for LaTeX, Word Perfect, and Word. You don't need to include categories, keywords, etc., though you are welcome to do so. Also, note that the ACM copyright notice is not required of submissions, only of accepted papers. Authors wishing to supply additional material to the reviewers beyond the 12-page limit can do so in clearly marked appendices, on the understanding that reviewers are not required to read the appendices. Submissions that do not meet these guidelines will not be considered. The submission deadline and length above are firm. Submissions will be carried out electronically via the Web, at the URL given above. Papers must be submitted in either PDF format, or as PostScript documents that are interpretable by Ghostscript, and they must be printable on US Letter sized paper. Individuals for which this requirement is a hardship should contact the program chair at least one week before the deadline. Submitted papers must have content that has not previously been published in other conferences or refereed venues; simultaneous submission to other conferences or refereed venues is unacceptable. Each paper should explain its contributions in both general and technical terms, clearly identifying what has been accomplished, saying why it is significant, and comparing it with previous work. Authors should strive to make the technical content of their papers understandable to a broad audience. Authors of accepted papers will be required to sign the ACM copyright form. Proceedings will be published by ACM Press. * Student Attendees ------------------- Students who have a paper accepted for the conference are offered student membership of SIGPLAN free for one year. As members of SIGPLAN they may apply for travel fellowships from the PAC fund. * Conference Chair ------------------ Colin Runciman University of York, UK * Program Chair --------------- Olin Shivers College of Computing Georgia Institute of Technology Atlanta, Ga. 30332-0280, USA shivers at cc.gatech.edu Phone: +1 404 385.00.91 Fax: +1 404 383.12.53 * Program Committee ------------------- Andrzej Filinski (DIKU, University of Copenhagen) Robby Findler (University of Chicago) Fritz Henglein (IT University of Copenhagen) Hugo Herbelin (INRIA) Ralf Hinze (Universität Bonn) Annie Liu (Stony Brook University) Benjamin Pierce (University of Pennsylvania) Todd Proebsting (Microsoft Corp.) Amr Sabry (University of Indiana) Zhong Shao (Yale University) Tim Sheard (OGI School of Science and Engineering) Eijiro Sumii (University of Tokyo) Andrew Wright (Cisco, Critical Infrastructure Assurance Group) * Accessing this document ------------------------- This document can be obtained in the following formats: HTML http://www.cc.gatech.edu/icfp03/cfp.html PostScript http://www.cc.gatech.edu/icfp03/cfp.ps PDF http://www.cc.gatech.edu/icfp03/cfp.pdf Plain text http://www.cc.gatech.edu/icfp03/cfp.txt * Change log ------------ 2003/2/5 Added program committee; revised submission deadline from 3/20 to 3/29; updated student travel-fellowship information. 2003/2/5 March 29 is Saturday, not Thursday. (March 20 is a Thursday.) 2003/2/7 Added Andrew Wright to PC list. 2003/2/9 Added URLs for accessing the CFP in various formats. From jleite@di.fct.unl.pt Tue, 25 Mar 2003 18:24:02 -00 Date: Tue, 25 Mar 2003 18:24:02 -00 From: =?iso-8859-1?Q?Jo=E3o_Alexandre_Leite?= jleite@di.fct.unl.pt Subject: [clean-list] CFP: DALT'03 - 1st Workshop on Declarative Agent Languages and Technologies =========================================================== S E C O N D C A L L F O R P A P E R S DALT 2003 First International Workshop on Declarative Agent Languages and Technologies Melbourne, Australia July 15th 2003 http://centria.di.fct.unl.pt/~jleite/dalt03/index.htm In conjunction with AAMAS 2003 2nd International Conference on Autonomous Agents and Multi-Agent Systems http://www.aamas-conference.org/ Submission: 11 of April, 2003 Post-Proceedings publishe by Springer-Verlag (LNAI) =========================================================== TECHNICAL DESCRIPTION Agent metaphors and technologies are ever more adopted to harness and govern the complexity of today's systems. As a consequence, the growing complexity of agent systems calls for models and technologies that promote system predictability, and enable feature discovery and verification. Recent advances in the area of logics and formal methods make declarative languages and technologies a mostly promising approach to the modeling and engineering of complex agent systems. DALT aims at fostering a discussion forum to export, on the one hand, such techniques into the broader community of agent researchers and practitioners and, on the other hand, to bring in the issues of real-world, complex, and possibly large-scale agent system design in the perspective of formal methods and declarative technologies. DALT 2003 will take place in Melbourne, Australia, in conjunction with AAMAS, the 2nd International Conference on Autonomous Agents and Multi-Agent Systems. Topics of interest include, but are not limited to: * Declarative agent communication and coordination languages * Knowledge-based and knowledge-intensive MAS * Modeling of agent rationality * Declarative approaches to the engineering of MAS * High level agent specification languages * Practical aspects of declarative agent programming and implementation * Formal methods for the specification and verification of MAS * Computational logics in MAS * Argumentation and dialectical systems in MAS * Declarative description of contracts and negotiation issues in MAS * Lessons learned from the design and implementation of MAS * Declarative paradigms for the combination of heterogeneous agents * Constraints and MAS * Declarative representation of policies and security in MAS SUBMISSIONS We welcome and encourage the submission of high quality, original papers, which are not simultaneously submitted for publication elsewhere. Papers should be written in English, formatted according to the Springer LNCS style, which can be obtained at (http://www.springer.de/comp/lncs/authors.html), and not exceed 16 pages including figures, references, etc. Send your paper in PostScript (PS) or Portable Document Format (PDF) to jleite@di.fct.unl.pt. IMPORTANT DATES * Submission, 11 of April, 2003 * Notification, 6 of May, 2003 * Camera Ready, 16 of May, 2003 PROCEEDINGS To encourage and promote the discussion, early and final versions of the accepted papers will be available online, at the workshop's web page, as soon as they are available. A printed volume with the proceedings will be available at the workshop. Authors of papers presented at the workshop will be asked to extend their contributions, possibly incorporating the results of the workshop discussion, to be included in the workshop post-proceedings. Post-proceedings will be published by Springer-Verlag as a volume of the Lecture Notes on Artificial Intelligence series (http://www.springer.de/comp/lncs/index.html). PROGRAM COMMITTEE Rafael Bordini, The University of Liverpool, UK Jeff Bradshaw, The University of West Florida, FL, USA Antonio Brogi, Università di Pisa, Italy Stefania Costantini, Università degli Studi di L'Aquila, Italy Yves Demazeau, Institut IMAG, Grenoble, France Jürgen Dix, The University of Manchester, UK Toru Ishida, Kyoto University, Japan Catholijn Jonker, Vrije Universiteit Amsterdam, The Netherlands Antonis Kakas, University of Cyprus, Cyprus Daniel Kudenko, University of York, UK Alessio Lomuscio, King's College, London, UK Viviana Mascardi, DISI, Genova, Italy Paola Mello, Università di Bologna, Italy John Jules Ch. Meyer, Universiteit Utrecht, The Netherlands Charles L. Ortiz, SRI International, Menlo Park, CA, USA Sascha Ossowski, Universidad Rey Juan Carlos, Madrid, Spain Luís Moniz Pereira, Universidade Nova de Lisboa, Portugal Jeremy Pitt, Imperial College, London, UK Ken Satoh, National Institute of Informatics, Tokyo, Japan Michael Schroeder, City University, London, UK Onn Shehory, IBM Research Lab in Haifa, Israel Carles Sierra, Spanish Research Council, Barcelona, Spain V.S. Subrahmanian, University of Maryland, MD, USA Francesca Toni, Imperial College, London, UK Wiebe van der Hoek, The University of Liverpool, UK Franco Zambonelli, Università di Modena, Italy ORGANIZING COMMITTEE Co-chairs: João Alexandre Leite (Contact Person) Universidade Nova de Lisboa jleite@di.fct.unl.pt Andrea Omicini Università di Bologna aomicini@deis.unibo.it Leon Sterling The University of Melbourne leon@cs.mu.oz.au Paolo Torroni Università di Bologna ptorroni@deis.unibo.it From fjh@cs.mu.oz.au Wed, 26 Mar 2003 18:27:00 +1100 Date: Wed, 26 Mar 2003 18:27:00 +1100 From: Fergus Henderson fjh@cs.mu.oz.au Subject: [clean-list] PPDP'03 submission deadline in one week Fifth ACM-SIGPLAN International Conference on Principles and Practice of Declarative Programming Uppsala, Sweden, 27-29 August 2003 IMPORTANT DATES Submission 29 March 2003 (strict) Notification 12 May 2003 Final Version 13 June 2003 SUBMISSION PAGE: http://www.lix.polytechnique.fr/Labo/Dale.Miller/ppdp03/ CONFERENCE PAGE: http://www.it.uu.se/ppdp03/ TOPICS (Not exhaustive): Logic, Functional, and Constraint Programming; Object-Oriented Programming; Concurrent Extensions; Mobile Computing; Integration of Paradigms; Proof Theoretic and Semantic Foundations; Program Design and Development; Type and Module Systems; Program Analysis and Verification; Program Transformation; Abstract Machines and Compilation; Programming Environments; and Application of Declarative Programming. PAPER SUBMISSIONS: Submissions must be made on or before 29 March 2003, noon Central European Time: this deadline is strict. Papers must be no more than 12 pages (including bibliography and appendices) and in standard ACM conference format. More details available at on the full Call-For-Papers: http://www.it.uu.se/ppdp03/. From gvidal@dsic.upv.es Tue, 25 Mar 2003 10:59:52 +0100 (CET) Date: Tue, 25 Mar 2003 10:59:52 +0100 (CET) From: German Vidal gvidal@dsic.upv.es Subject: [clean-list] WFLP'03: Deadline extension --> April 2 ********************************************************************** NEW: The deadline for submissions to WFLP 2003 has been extended to April 2, 2003 ********************************************************************** ====================================================================== FINAL CALL FOR PAPERS WFLP 2003 12th Int'l Workshop on Functional and (Constraint) Logic Programming June 12-13, 2003, Valencia (Spain) http://www.dsic.upv.es/~rdp03/wflp/ ====================================================================== WFLP is the International Workshop on Functional and (Constraint) Logic Programming. WFLP'03, the twelfth in the series, will be held in Valencia, Spain, June 12-13, 2003, at the Federated Conference on Rewriting, Deduction and Programming (RDP'03) http://www.dsic.upv.es/~rdp03/ The WFLP workshops aim at bringing together researchers interested in functional programming, (constraint) logic programming, as well as their integration. It promotes the cross-fertilizing exchange of ideas and experiences among researches and students from the different communities interested in the foundations, applications, and combina- tions of high-level, declarative programming languages and related areas.The technical program of the workshop will include invited talks, presentations of refereed papers and demo presentations. Previous editions of the workshop have been held in Grado (Italy), Kiel (Germany), Benicassim (Spain), Grenoble (France), Bad Honnef (Germany), Schwarzenberg (Germany), Marburg (Germany), Rattenberg (Germany), and Karlsruhe (Germany). ---------------------------------------------------------------------- TOPICS OF INTEREST WFLP'03 solicits papers in all areas of functional and (constraint) logic programming, including (but not limited to): * Language Design: modules and type systems, multi-paradigm languages, concurrency and distribution, objects * Foundations: formal semantics, rewriting and narrowing, nonmonotonic reasoning, dynamics, type theory * Implementation: abstract machines, parallelism, compile-time and run-time optimizations, interfacing with external languages * Transformation and Analysis: abstract interpretation, specialization, partial evaluation, program transformation, meta-programming * Software Engineering: design patterns, specification, verification and validation, debugging, test generation * Applications: declarative programming in education and industry, domain-specific languages, visual/graphical user interfaces,embedded systems, WWW applications, knowledge representation and machine learning, deductive databases, advanced programming environments and tools The main focus is on new and original research results but submissions describing innovative products, prototypes under development or interesting experiments (e.g., benchmarks) are also encouraged. ---------------------------------------------------------------------- IMPORTANT DATES Submission of papers: Wednesday, April 2, 2003 Notification of acceptance: Friday, April 25, 2003 Camera-ready papers: Sunday, May 11, 2003 Workshop: June 12 - 13, 2003 ---------------------------------------------------------------------- SUBMISSION Authors are invited to submit an extended abstract (no longer than 12 pages including figures and references) or a system description (no longer than 4 pages) in Postscript or PDF format (Springer LNCS style) via email to gvidal@dsic.upv.es before April 2, 2003. Submissions should include the title, authors' names, affiliations, addresses, and e-mail. ---------------------------------------------------------------------- PUBLICATION Accepted papers will be included in the preliminary proceedings that will be available at the workshop. After the workshop, authors of the best abstracts will be invited to submit full papers.These full papers will be reviewed and accepted papers will appear in the Electronic Notes in Theoretical Computer Science (Elsevier). ---------------------------------------------------------------------- BEST NEWCOMER AWARD An award will be given to the best paper exclusively written by one or several young researchers who have not yet obtained their PhD degrees. Papers written in this category should be clearly marked "Student papers" in the submission. ---------------------------------------------------------------------- PROGRAM COMMITTEE Maria Alpuente (Technical University of Valencia, Spain) Sergio Antoy (Portland State University, USA) Annalisa Bossi (Universita Ca' Foscari di Venezia, Italy) Olaf Chitil (University of York, UK) Rachid Echahed (Institut IMAG, France) Sandro Etalle (University of Twente, The Netherlands) Moreno Falaschi (Universita di Udine, Italy) Michael Hanus (CAU Kiel, Germany) Yukiyoshi Kameyama (University of Tsukuba, Japan) Herbert Kuchen (University of Muenster, Germany) Michael Leuschel (University of Southampton, UK) Juan Jose Moreno-Navarro (Universidad Politecnica de Madrid, Spain) Ernesto Pimentel (University of Malaga, Spain) Mario Rodriguez-Artalejo (Universidad Complutense de Madrid, Spain) German Vidal (Technical University of Valencia, Spain) ---------------------------------------------------------------------- LOCAL ORGANIZING COMMITTEE Elvira Albert Santiago Escobar Cesar Ferri Jose Hernandez Carlos Herrero Pascual Julian Marisa Llorens Gines Moreno Javier Oliver German Vidal Alicia Villanueva ---------------------------------------------------------------------- FURTHER INFORMATION WFLP 2003: http://www.dsic.upv.es/~rdp03/wflp Workshop contact: gvidal@dsic.upv.es RDP 2003: http://www.dsic.upv.es/~rdp03 From kdijken@tdn.nl Mon, 31 Mar 2003 12:24:40 +0200 Date: Mon, 31 Mar 2003 12:24:40 +0200 From: Dijken, Koen van kdijken@tdn.nl Subject: [clean-list] constant Tree as pattern ? Hello, I am a newcomer to Clean, and have the following question (Clean 2.0.2) about the following piece of code: :: Tree a = nil | Node a (Tree a) (Tree a) test :: (Tree Int) -> Int test (Node 1 nil nil) = 1 test (Node 2 nil nil) = 2 test = 3 Start = test (Node 1 nil nil) compiles fine and gives 1 as the result of the Start function When i replace Start with Start = test (Node 2 nil nil) however, i still get 1 as the result of Start when I expext 2 as the result. >From the language report (chapter 3.2) I understand I can use any kind of constant as a pattern. In my understanding of Clean at this moment the expression (Node 2 nil nil) is a constant of type (Tree Int). What is the flaw in my thinking ? Koen van Dijken From vissers@theochem.kun.nl Mon, 31 Mar 2003 15:26:04 +0200 (CEST) Date: Mon, 31 Mar 2003 15:26:04 +0200 (CEST) From: G.W.M. Vissers vissers@theochem.kun.nl Subject: [clean-list] constant Tree as pattern ? Hello Koen, are you sure that the program as you sent it compiles? Using Clean 2.0.2 on a Linux pc the compiler rightly complains about two things: Parse error [tmp.icl,3;13,Algebraic type: constructor definitions]: constructor name expected instead of nil and after changing the definition to :: Tree a = Nil | Node a (Tree a) (Tree a) it complains about the missing argument in the "test" function: Error [tmp.icl,8,test]: This alternative has 0 arguments instead of 1. Fixing that: module tmp :: Tree a = Nil | Node a (Tree a) (Tree a) test :: (Tree Int) -> Int test (Node 1 Nil Nil) = 1 test (Node 2 Nil Nil) = 2 test _ = 3 Start = test (Node 2 Nil Nil) This works for me (i.e. gives 2). regards, Gé > Hello, > > I am a newcomer to Clean, and have the following question (Clean 2.0.2) > about the following piece of code: > > :: Tree a = nil | Node a (Tree a) (Tree a) > > test :: (Tree Int) -> Int > test (Node 1 nil nil) = 1 > test (Node 2 nil nil) = 2 > test = 3 > > Start = test (Node 1 nil nil) > > compiles fine and gives 1 as the result of the Start function > > When i replace Start with > > Start = test (Node 2 nil nil) > > however, i still get 1 as the result of Start when I expext 2 as the result. > > >From the language report (chapter 3.2) I understand I can use any kind of > constant as a pattern. In my understanding of Clean at this moment the > expression (Node 2 nil nil) is a constant of type (Tree Int). > > What is the flaw in my thinking ? > > Koen van Dijken > > > > > _______________________________________________ > clean-list mailing list > clean-list@cs.kun.nl > http://www.cs.kun.nl/mailman/listinfo/clean-list > From igouy@yahoo.com Wed, 2 Apr 2003 09:25:25 -0800 (PST) Date: Wed, 2 Apr 2003 09:25:25 -0800 (PST) From: isaac gouy igouy@yahoo.com Subject: [clean-list] Re: eof for console input Some file functions can be used with redirected textfile input from a windows console. (prog.exe -con < input.txt) freadc, freadi, freadr all fail at "end-of-file". So this works fine: countchars console count # (ok, c, console) = freadc console | not ok = count // "end-of-input" = countchars console (count+1) The "buffered" reads (freads, freadsubstring, freadline) don't seem to be consistent with this behaviour. They don't recognise "end-of-file". best wishes, Isaac __________________________________________________ Do you Yahoo!? Yahoo! Tax Center - File online, calculators, forms, and more http://tax.yahoo.com From EZuurbier@Abz.nl Fri, 4 Apr 2003 10:07:20 +0200 Date: Fri, 4 Apr 2003 10:07:20 +0200 From: Erik Zuurbier EZuurbier@Abz.nl Subject: [clean-list] constructor variable mistaken for uniqueness attribute This message is in MIME format. Since your mail reader does not understand this format, some or all of this message may not be legible. ------_=_NextPart_001_01C2FA81.374E03A0 Content-Type: text/plain Hi all, I defined a datatype for tries as follows: :: Trie char meaning :== [Branche char meaning] :: Branche char meaning = C char (Trie char meaning) | M meaning and all went well: I defined all desired operations for tries. But then I thought the choice of lists to represent the fan-out was too constrained: for big alphabets look-up should be faster if instead of a list a binary tree or whatever other tree-structure could be used. So I thought: why not abstract out the particular list-type-constructor? So I tried: :: Trie c char meaning :== c (Branche c char meaning) :: Branche c char meaning = C char (Trie c char meaning) | M meaning But this generated the remarkable error message: Error [TrieGen.icl,14,Trie]: c uniqueness attribute not allowed What am I doing wrong? Regards Erik Zuurbier (By the way, this is Clean 1.3.2. If this problem does not occur in Clean 2.X, sorry for the fuss.) ------_=_NextPart_001_01C2FA81.374E03A0 Content-Type: text/html Content-Transfer-Encoding: quoted-printable constructor variable mistaken for uniqueness attribute

Hi all,

I defined a datatype for tries as = follows:

:: Trie char meaning :=3D=3D [Branche = char meaning]
:: Branche char meaning =3D C char = (Trie char meaning) | M meaning

and all went well: I defined all = desired operations for tries. But then I thought the choice of lists to = represent the fan-out was too constrained: for big alphabets look-up = should be faster if instead of a list a binary tree or whatever other = tree-structure could be used.

So I thought: why not abstract out the = particular list-type-constructor? So I tried:

:: Trie c char meaning :=3D=3D c = (Branche c char meaning)
:: Branche c char meaning =3D C char = (Trie c char meaning) | M meaning

But this generated the remarkable = error message:

Error [TrieGen.icl,14,Trie]: c = uniqueness attribute not allowed

What am I doing wrong?

Regards Erik Zuurbier

(By the way, this is Clean 1.3.2. If = this problem does not occur in Clean 2.X, sorry for the fuss.)



------_=_NextPart_001_01C2FA81.374E03A0-- From siegfried.gonzi@stud.uni-graz.at Sat, 03 May 2003 15:40:33 +0200 Date: Sat, 03 May 2003 15:40:33 +0200 From: Siegfried Gonzi siegfried.gonzi@stud.uni-graz.at Subject: [clean-list] Linking Clean to DISLIN Lets assume I have a plotting library DISLIN which lets me use it as follows: [exa_c.c for example has the DISLIN header file: #include "dislin.h"] gcc -o exa_c exa_c.o -L$DISLIN -ldislnc -lm creates ./exa_c According to the DISLIN manual the -L option can be omitted if links to the DISLIN libraries are created in /usr/lib (note my dislin libraries reside in: /usr/local/dislin) ln -s $DISLIN/lib/dislin-7.6.so libdislin.so.7 ln -s libdislin.so.7 libdislin.so ln -s $DISLIN/lib/dislnc-7.6.so libdislnc.so.7 ln -s libdislnc.so.7 libdislnc.so ln -s $DISLIN/lib/dislin-7.6.a libdislin.a ln -s $DISLIN/lib/dislnc-7.6.a libdislnc.a I wrote the above because I do not have any clue, but a C expert should easily discern what my post is about. I think I have a basic understanding of including C functions in Clean (see also my post the other day: http://groups.google.com/groups?dq=&hl=en&lr=&ie=UTF-8&oe=UTF-8&group=comp.lang.functional&selm=3EB1FCEB.5070408%40kfunigraz.ac.at) But I am a bit baffled now because the header functions of DISLIN expect float-pointers. I am not sure how to circumvent this but with wrapper functions: test_plot_c.c == #include #include // dislin #include void clean_qplot (double *xray, double *yray, int n) { qplot(&xray[0], &yray[0], n); } == After making the object file (gcc -o test_plot_c.c) I get the warning message that qplot expects float pointers, but this was my first try and I do not know whether they become automatically coerced when passing double-pointers from Clean to float-pointers in C. The original DISLIN function is: void qplot(float *xray,float *yray,int n); But this is not the problem (yet) I have no clue how to link the aforementioned object file with DISLIN and test_plot_main.icl alike?: clm -l test_plot_c.o -ldislnc test_plot_main does not work [note: linking an ordinary C program with DISLIN is as follows: gcc -o exa_c exa_c.o -L$DISLIN -ldislnc -lm] I am not sure whether it is possible to create a /linked/ test_plot_c.o in advance? Is it possible to make test_plot_c.o which already has DISLIN linked and passing this then on to: clm -l test_plot_c.o test_plot_main And how to pass floating-point vectors to a C-function? I mean DISLIN has 570 header functions which expects mostly float values. I wrote a DISLIN binding for Bigloo (Scheme) and could use floating-point values. One way would be to copy around things, but this is cumbersome: 1) my_malloc in a Clean program 2) copying a Clean list to my_malloc 3) passing this my_malloc to a DISLIN C wrapper function 4) before the wrapper function is going to forward the passed pointer to a native DISLIN function it becomes again converted to a float-pointer: (double *p) -> (float *p) DISLIN (www.dislin.de) is a high quality plotting library for Python, Perl, Java, C, Fortran 77, Fortran 90 and my inofficial (not released yet) binding to Bigloo (Scheme). My super computing farm: SuSE 8 Linux, Clean 2.02 Regards, S. Gonzi From siegfried.gonzi@stud.uni-graz.at Sun, 04 May 2003 08:40:04 +0200 Date: Sun, 04 May 2003 08:40:04 +0200 From: Siegfried Gonzi siegfried.gonzi@stud.uni-graz.at Subject: [clean-list] Linking Clean to DISLIN I am really surprised how far I got yesterday. I found a way how to create and link the shared DISLIN library in advance: - gcc -fIPC -c dis_c.c - gcc -shared -o libmy.so dis_c.o -L/usr/local/dislinc -lm - clm libmy.so dis_main I use it in dis_main: import libmy I could even made my first quickplot yesterday. To circumvent the following: qplot(float *ray,float *yray,int n); I did: I use my_malloc and store_double_in_float_p: void *my_malloc(int size_in_bytes) { return malloc (size_in_bytes); } the trick and cheating then is to pass a created 4*n byte my_malloc to a C-function which expects otherwise a float-pointer (4 bytes): float *store_double_in_float_p(float *p,int offset,double value) { p[offset]=(float)value; return p; } /BUT/ in dis.h I specify: double *store_double_in_float(int *p,int offset,double value); This is akward though. I did it with "search replace" for every of the 570 DISLIN function. I had also to change short to int; unsigned short to int;long to int. Otherwise "htoclean dis.h" wouldn't work. But I haven't found out yet how to pass *char. Do I also have to copy around things then? A typical session could be: == //curves:: [Real] [Real] -> Int curves x y # n = length x //Fill C-floating-point values # xf = FillMyMalloc (my_malloc (4*n)) x # yf = FillMyMalloc (my_malloc (4*n)) y // DISLIN functions starts here #! metafl = metafl "eps" #! setfil = setfil "/home/gonzi/krishna.eps" #! setpag = setpag 2000.0 2000.0 #! disini = disini #! erase = erase #! complx = complx #! winmod = winmod "NONE" #! texmod = texmod "ON" #! labdig = labdig 1 "Y" #! labdig = labdig 1 "X" #! name = name "x" "X" #! name = name "y" "Y" #! graf = graf 0.0 10.0 0.0 10.0 0.0 10.0 0.0 2.0 #! xy_plot2 = xy_plot x y #! curve = curve x y #! endgrf = endgrf #! disfin = disfin = (disfin,xy_plot2,setfil) Start = curves [1.0,2.0,3.0,4.0] [1.2,3.4,2.56,2.34] == [e.g. texmod "ON" means you could use LaTeX commands for x-y axis annotation] This should produce a postscipt output and a quickplot to the screen. The qickplot on the screen works but not the postscript output. This is clear because I have no clue how topass from Clean *char to a C function: how?: foo(* char); in Clean?: foo("mama mia")? However, the curious thing actually is I do not get an error message, which means "setfil=setfil "/home/gonzi/krishna.eps" for example does not become worked up. I think it has to do with lazy evaluation because I specify at my exit point only: (disfin,xy_plot2); this means only my quickplot becomes solved because it does not need disini and disfin (see postcript). But I think it cannot be the way to list again all the DISLIN functions at this exit-point? I am not sure whether the above is safe, because I have written 570 wrapper functions in Bigloo: dislin-qplot,... In Clean it would be possible to write: clean_qplot,... Or is there a way to specify from which module they come from because writing again 570 wrappers is way to time consuming for me. Regards, S. Gonzi PS: FillMyMalloc for example: // p has been created with: my_malloc (4*n) == FillmyMalloc:: Int [Real] -> Int FillMyMalloc p ls = store_it p [(x,y)\\y<-ls & x<-[0..]] where store_it::Int [(Int,Real)] -> Int store_it p [] = p store_it p [(x,y):t] = store_it (store_double_in_float_p p x y) t == == xy_plot:: [Real] [Real] -> Int xy_plot x y # n = length x # xf = FillMyMalloc (my_malloc (4*n)) x # yf = FillMyMalloc (my_malloc (4*n)) y //DISLIN function = qplot xf yf n == From siegfried.gonzi@stud.uni-graz.at Mon, 05 May 2003 08:31:49 +0200 Date: Mon, 05 May 2003 08:31:49 +0200 From: Siegfried Gonzi siegfried.gonzi@stud.uni-graz.at Subject: [clean-list] Re: (clean-list digest): Linking Clean to DISLIN the third > > > To make it short. I think I know now how to pass strings but I do not know whether the following becomes worked through step after step, because it does not work properly: == symbols #! metafl2=metafl (p_to_char "cons") #! dsini2=disini #! graf2=c_graf 0.0 10.0 0.0 2.0 0.0 10.0 0.0 2.0 #! disfin2=disfin = [metafl2,disini2,graf2,disfin2] == [p_to_char is my pointer to chars: metafl(char *s)] metafl creates the plot-format (this works); disini starts the process (this works); graf sets the coordinate system and disfin (this works) closes DISLIN. The above works und Python, C, Bigloo but I get wrong results under Clean. I get always the error message that the origin of the coordinate system is out of range. Note: c_graf is a wrapper to graf, because I think there is no way to pass a single C-float: void c_graf(double x,double y,...) { graf((float)x,(float)y,...); } First I thought this wrapper passes wrong arguments to graf, but it doesn't. If I use only metafl,disini and disfin everything works. Regards, S. Gonzi From siegfried.gonzi@stud.uni-graz.at Tue, 06 May 2003 11:23:03 +0200 Date: Tue, 06 May 2003 11:23:03 +0200 From: Siegfried Gonzi siegfried.gonzi@stud.uni-graz.at Subject: [clean-list] Python's "fix" function in Clean > > > I once complaint about Clean's scarce libraries for handling formatted output. The following is a first step: Maybe you are already familar with Python's fix function: == from fpformat import* fix(2.23231312123123312312,2) == fix convertes a number to a specific precision and if needed fills up traling zeros and delivers a string for formatted output, e.g: fix(2.3,3) -> 2.300 I wrote a similar function for Clean (you can literally translate it to Haskell), with the caveat that it only works the same as Python's fix for floating point values with single precision. The crux actually is that Clean's native "toString" function "fails" when converting a huge integer number. I think Python uses some bit representation, because this works under Python: fix(32231231123123124433422352545.3545544545,123) My Clean version works right with the small "drawback" that if a number is greater than 10^9 it is given back as toString(x) and if the precision is specified greater than 9 it will be set back to 9, e.g. (fix 2.3 120) would result in 2.300000000 and not in 2.300000000000..... as it would happen under Python's fix. But who wants to store a number with 120 "pseudo" precision digits? You can convert Clean's fix function for formatted output: == module fix9 import StdEnv fix:: Real Int -> String fix val n # n = (if (n>9) 9 n) | abs(val)>=10.0^9.0 = toString(val) | n<0 = "0" | n==0 = toString(toInt(round val)) # exp_n = 10.0^toReal(n) # f = (round (val*exp_n))/exp_n # f = abs val # t = toInt(truncate f) # s = toString(toInt(round (exp_n*(f-toReal(t))))) # nzeros = length [x\\x<-:s] = (whatSign val)+++(toStringt) +++"."+++{'0'\\x<-[1..(n-nzeros)]}+++s where round:: Real -> Real round x = toReal(toInt(x)) // truncate:: Real -> Real truncate x | x<0.0 = toReal(toInt(x+0.5)) = toReal(toInt(x-0.5)) // whatSign::Real -> String whatSign x | x<0.0 = "-" = "" //Start = fix (-0.000011) 2 //Start = fix 2.333333 1 //Start = fix 0.01 3 //Start = fix 0.01 0 //Start = fix -2322332231312312123312123.33 12 Start = fix 1234.34 5 == fix 0.03 0 --> "0" fix -2.334444 1 --> "-2.3" fix 2.3454 5 --> "2.34540" fix 2.89 1 --> "2.9" fix (10.0^12.0) 123 --> "1e12" (Clean's native toString and Python would put out a very long string; but as I said my function would also work right if toString were not limited to 32bit, I think) Regards, S. Gonzi From siegfried.gonzi@stud.uni-graz.at Tue, 06 May 2003 12:13:19 +0200 Date: Tue, 06 May 2003 12:13:19 +0200 From: Siegfried Gonzi siegfried.gonzi@stud.uni-graz.at Subject: [clean-list] Python's "fix" function in Clean Jerzy K. pointed out that I had a typo somewhere: f = abs(val) should be changed to: f=abs f Checked my Scheme implementation and it turned out that I was making a typo during translation. S. Gonzi > From a_s_soares@yahoo.com.br Tue, 13 May 2003 14:27:01 -0300 (ART) Date: Tue, 13 May 2003 14:27:01 -0300 (ART) From: =?iso-8859-1?q?Alexsandro=20Soares?= a_s_soares@yahoo.com.br Subject: [clean-list] Artificial Intelligence in Clean Dear All, I´m interested in the use of modern functional programming languages in Artificial Intelligence. At the moment, I'm trying with Clean. So, I have some questions: 1 - Is there anyone that used Clean for Neural Network, Genetic Programming, Fuzzy Logic, heuristic search, expert systems or other areas of Artificial Intelligence? 2 - How efficient are these programs compared with equivalent implementations in C or other languages (Haskell, OCaml, etc.)? Are there source codes available? 3 - Is Clean (like others lazy, strongly typed languages) inappropriate for this task? I´m a novice programmer in Clean, and I have a last question: How can I multiply two matrix A and B, and put the result destructivly in another one? Something like: C = A x B. This is important for Neural Networks implementation. Thanks in advance for any answer you can offer. Regards, Alex _______________________________________________________________________ Yahoo! Mail O melhor e-mail gratuito da internet: 6MB de espaço, antivírus, acesso POP3, filtro contra spam. http://br.mail.yahoo.com/ From pieter@cs.kun.nl Tue, 13 May 2003 21:46:38 +0200 Date: Tue, 13 May 2003 21:46:38 +0200 From: Pieter Koopman pieter@cs.kun.nl Subject: [clean-list] Artificial Intelligence in Clean Dear Alex, At 14:27 13-5-2003 -0300, Alexsandro Soares wrote: >I´m interested in the use of modern functional >programming languages in Artificial Intelligence. At >the moment, I'm trying with Clean. So, I have some >questions: > >1 - Is there anyone that used Clean for Neural >Network, Genetic Programming, Fuzzy Logic, heuristic >search, expert systems or other areas of Artificial >Intelligence? Very recently we have started to work on this area in Nijmegen. Not much results yet, but what has been done looks OK. >2 - How efficient are these programs compared with >equivalent implementations in C or other languages >(Haskell, OCaml, etc.)? Are there source codes >available? I expect just like any other program: it depends on how clever you are in programming. There is no reason why Clean programs should be much slower than C-programs. Usually there is at most a factor of 2 difference in speed. Sometimes C wins, sometimes Clean wins. >3 - Is Clean (like others lazy, strongly typed >languages) inappropriate for this task? Clean is strongly typed. But why should strongly typed languages be inappropriate? >I´m a novice programmer in Clean, and I have a last >question: How can I multiply two matrix A and B, and >put the result destructivly in another one? Something >like: C = A x B. This is important for Neural Networks >implementation. Use unique datastructures for you matrices. Have a look at the Clas library at http://www.cs.kun.nl/~clean/Download/Download_Libraries/clas/clas.html. Unfortunatly, this lib is still written in Clean 1.3, but conversion to Clean 2.0 should be straight forward. Tell me if there you encounter problems. Have fun, Pieter Koopman From khamenya@mail.ru Wed, 14 May 2003 01:34:34 +0200 Date: Wed, 14 May 2003 01:34:34 +0200 From: Valery A.Khamenya khamenya@mail.ru Subject: [clean-list] Artificial Intelligence in Clean Hello Pieter, PK> Usually there is at most a factor of 2 difference in PK> speed. Sometimes C wins, sometimes Clean wins And when then Clean wins?! Any true examples? I am on the side of Clean :) actually, I am interesting when some Functional-Programming-based approaches will show finally its _performance_ benefits *without* highly parallelized architectures. It would be interesting. -- Best regards, V.A.Khamenya From fzuurbie@inter.nl.net Wed, 14 May 2003 07:26:15 UT Date: Wed, 14 May 2003 07:26:15 UT From: fzuurbie@inter.nl.net fzuurbie@inter.nl.net Subject: [clean-list] Artificial Intelligence in Clean This is a multi-part message in MIME format. --_----------=_105289717511272 Content-Disposition: inline Content-Length: 2006 Content-Transfer-Encoding: binary Content-Type: text/plain Alex Soares wrote: > 1 - Is there anyone that used Clean for Neural > Network, Genetic Programming, Fuzzy Logic, heuristic > search, expert systems or other areas of Artificial > Intelligence? I have Simulated Annealing running, neatly divided in the optimization engine and the specific function to be optimized. The optimization engine contains an extra feature: you can call different state perturbation functions, stochastically depending on the 'temperature' and state properties. As a simple example, in the travelling salesman problem this lets you use wild path changes at high temperatures and gradually shift to very local and greedy path improvements as the temperature drops. I also have a version of Simulated Annealing running for continuous variables, but without the extra feature. I translated that from the 'Numerical Recipes in Fortran' book. > 2 - How efficient are these programs compared with > equivalent implementations in C or other languages > (Haskell, OCaml, etc.)? I have no evidence on that. I never tried implementations in other languages. But the algorithms do not contain constructs with an inherent slow down, such as lists where arrays would be more appropriate. > Are there source codes available? Sure, let me know and I'll find some time to gather the modules involved. > 3 - Is Clean (like others lazy, strongly typed > languages) inappropriate for this task? My experience is that Clean is appropriate: bugs are not so common and changes are fairly easy to make. I had some difficulties getting some functions past the uniqueness type checker though. And some functions initially built up heap where I expected them to release garbage. Such problems can keep you staring at the screen for a while. So if your goal is just to get AI-algorithms runnning, no matter what, watch out: programming in Clean can be very rewarding from an intellectual point of view but it takes a lot of perseverance at times. Regards Erik Zuurbier --_----------=_105289717511272-- From siegfried.gonzi@stud.uni-graz.at Wed, 14 May 2003 09:52:54 +0200 Date: Wed, 14 May 2003 09:52:54 +0200 From: Siegfried Gonzi siegfried.gonzi@stud.uni-graz.at Subject: [clean-list] Artificial Intelligence in Clean Pieter Koopman wrote: / / >Use unique datastructures for you matrices. >Have a look at the Clas library at >http://www.cs.kun.nl/~clean/Download/Download_Libraries/clas/clas.html. >Unfortunatly, this lib is still written in Clean 1.3, but conversion to >Clean 2.0 should be straight forward. Tell me if there you encounter problems. There are small hurdles with the Clas library. It uses at some places "ArrayElem". The new Clean 2 compiler expects (a e) or something like this. I had no luck to adapt the new scheme but removing ArrayElem and using explicit types helps. But this solution is not contending and it would be good if one could have a look at the CLAS library. ArrayElem occurs only at 5 or 6 places. One has also to comment out the last few lines in the slicing module in order to get the module through the compiler. S. Gonzi From a_s_soares@yahoo.com.br Wed, 14 May 2003 08:44:22 -0300 (ART) Date: Wed, 14 May 2003 08:44:22 -0300 (ART) From: =?iso-8859-1?q?Alexsandro=20Soares?= a_s_soares@yahoo.com.br Subject: [clean-list] Simulated Annealing Hi Erik, I'm interested in your Simulated Annealing implementation. Could you send me the code? I agree with you: "programming in Clean can be very rewarding from an intellectual point of view but it takes a lot of perseverance at times". So, I expect to stay in this state of grace until it is replaced by a state of glory... Amen Regards, Alex _______________________________________________________________________ Yahoo! Mail O melhor e-mail gratuito da internet: 6MB de espaço, antivírus, acesso POP3, filtro contra spam. http://br.mail.yahoo.com/ From bfulgham@debian.org Fri, 16 May 2003 14:40:06 -0600 Date: Fri, 16 May 2003 14:40:06 -0600 From: bfulgham@debian.org bfulgham@debian.org Subject: [clean-list] Debian Package Available I've created an initial package of Clean under Debian ix86. I've got a PowerPC build in the works, and an attempt at SPARC, but these are going to Take some time. All versions are/will be available at: http://people.debian.org/~bfulgham/clean The advantage of using this package over the official Clean site tarball is that it is built into the standard Debian file system hierarchy, menu system, and package management system. This means you can launch the XView based programming environment from the usual X-Windows menu manager on your system. Let me know if you encounter any problems with the software. Thanks, -Brent From siegfried.gonzi@stud.uni-graz.at Sat, 17 May 2003 16:16:58 +0200 Date: Sat, 17 May 2003 16:16:58 +0200 From: Siegfried Gonzi siegfried.gonzi@stud.uni-graz.at Subject: [clean-list] Re: (clean-list): 1. Debian Package Available clean-list-admin@cs.kun.nl wrote: > > >The advantage of using this package over the official Clean site tarball is >that it is built into the standard Debian file system hierarchy, menu >system, and package management system. This means you can launch the XView >based programming environment from the usual X-Windows menu manager on >your system. > Has one ever tried to use the IDE on SuSE 8 Linux? I can install the IDE; even able to create a project but when I try to compile this project under Clean nothing happens. After doing "make io" I do not get any error messages that the Xview libraries cannot be found. The problem actually is that the new profiling mechanism of the Unix/Linux versions of Clean becomes useless, because you need the IDE to specify that you want profiling. Couldn't figure out with the assistance of "man clm" how to do it otherwise. S. Gonzi > From bfulgham@debian.org Tue, 3 Jun 2003 15:18:42 -0600 Date: Tue, 3 Jun 2003 15:18:42 -0600 From: bfulgham@debian.org bfulgham@debian.org Subject: [clean-list] Gtk ObjectIO Krasimir Angelov has spent a fair amount of time taking the original Clean ObjectIO library port to Haskell, and bringing it forward to the current version of the Glasgow Haskell compiler. As part of this work, he created an initial port of ObjectIO to the Gtk+ toolkit (see http://www.gtk.org. I started from Karsimir's Gtk+ sources, and ported them *back* to Clean, resulting in a partially-functioning ObjectIO under Linux. Right now most of the basic windowing functionality is there, at least well enough for the "Hello, World", and "Compare" programs to run. "Clipboard" works, though I haven't bound the clipboard code yet, so you get the GUI but it doesn't do anything. I'm now trying to get the Towers of Hanoi program to work (th first program heavily using drawing primitives), and I'm running into a confusing problem. It starts up, draws the root window frame, then terminates with a "Heap Full" error from Clean. It seems unlikely that the heap is actually full, since it hasn't even completed the initialization process. Does anyone have any experience debugging these kinds of problems under Clean? When I get a clean segfault in the Gtk binding, I can generally see what's going on. But when the error is announced from the Clean side I can't see what's going on. Are there some switchs or options that can be used to activate better tracing or reporting? Clearly something is not getting cleaned up from the Heap, but how can I tell what's not getting collected? Any help would be greatly appreciated. Thanks, -Brent From diederik@cs.kun.nl Tue, 3 Jun 2003 23:35:46 +0200 Date: Tue, 3 Jun 2003 23:35:46 +0200 From: Diederik van Arkel diederik@cs.kun.nl Subject: [clean-list] Gtk ObjectIO On Tuesday, June 3, 2003, at 11:18 PM, bfulgham@debian.org wrote: > Krasimir Angelov has spent a fair amount of time taking the original > Clean > ObjectIO library port to Haskell, and bringing it forward to the > current > version of the Glasgow Haskell compiler. As part of this work, he > created an initial port of ObjectIO to the Gtk+ toolkit (see > http://www.gtk.org. > > I started from Karsimir's Gtk+ sources, and ported them *back* to > Clean, > resulting in a partially-functioning ObjectIO under Linux. Right now > most > of the basic windowing functionality is there, at least well enough for > the "Hello, World", and "Compare" programs to run. "Clipboard" works, > though I haven't bound the clipboard code yet, so you get the GUI but > it doesn't do anything. > > I'm now trying to get the Towers of Hanoi program to work (th first > program > heavily using drawing primitives), and I'm running into a confusing > problem. > It starts up, draws the root window frame, then terminates with a > "Heap Full" error from Clean. It seems unlikely that the heap is > actually > full, since it hasn't even completed the initialization process. > > Does anyone have any experience debugging these kinds of problems under > Clean? When I get a clean segfault in the Gtk binding, I can generally > see what's going on. But when the error is announced from the Clean > side > I can't see what's going on. > > Are there some switchs or options that can be used to activate better > tracing or reporting? Clearly something is not getting cleaned up from > the Heap, but how can I tell what's not getting collected? > > Any help would be greatly appreciated. > > Thanks, > > -Brent Ooh, excellent that someone's working on this. I currently don't have Clean running under Linux so I can't directly help you there but I can tell you that "Heap Full" doesn't necessarily actually mean that the heap is full on the other platforms when you are messing around with C interfacing. I usually get this kind of error (or other crashes) from incorrectly specified bindings. If you could mail me or make available your current version I'll see if I can get it running undert Gtk on MacOS X. That should help pinpoint the trouble. Regards, Diederik van Arkel From ka2_mail@yahoo.com Wed, 4 Jun 2003 00:09:51 -0700 (PDT) Date: Wed, 4 Jun 2003 00:09:51 -0700 (PDT) From: Krasimir Angelov ka2_mail@yahoo.com Subject: [clean-list] Re: Gtk ObjectIO > I started from Karsimir's Gtk+ sources, and ported > them *back* to Clean, > resulting in a partially-functioning ObjectIO under > Linux. Good news. Please keep me informed for future development of ObjectIO. If you need to get some piece of platform independent C code you can browse the sources of my new project htoolkit.sourceforge.net. I hope that low level C code can be reused from languages different from Haskell. Best regards, Krasimir __________________________________ Do you Yahoo!? Yahoo! Calendar - Free online calendar with sync to Outlook(TM). http://calendar.yahoo.com From emailit2evert@yahoo.com Wed, 4 Jun 2003 02:49:41 -0700 (PDT) Date: Wed, 4 Jun 2003 02:49:41 -0700 (PDT) From: Evert Tigchelaar emailit2evert@yahoo.com Subject: [clean-list] Finding the biggest Int in an Int array Hi I am new to Clean. How to get the bigest Int from an Int Array? module Test import StdEnv Start :: Int Start = 1 // Returns the bigest number of two Int's. getBig :: Int Int -> Int getBig a b = if(a > b) a b // should return the biggest Int from the Int Array. getBigest :: {Int} Int Int -> Int getBigest myArray pos bignr = if(pos == 0) getBigest myArray (pos + 1)(bignr = (getBig myArray.[pos] (myArray.[pos] -1))) getBigest myArray (pos + 1)(bignr = (getBig myArray.[pos] bignr)) __________________________________ Do you Yahoo!? Yahoo! Calendar - Free online calendar with sync to Outlook(TM). http://calendar.yahoo.com From bfulgham@debian.org Wed, 4 Jun 2003 10:41:22 -0600 Date: Wed, 4 Jun 2003 10:41:22 -0600 From: bfulgham@debian.org bfulgham@debian.org Subject: [clean-list] Re: Gtk ObjectIO > Good news. Please keep me informed for future > development of ObjectIO. If you need to get some piece > of platform independent C code you can browse the > sources of my new project htoolkit.sourceforge.net. > I hope that low level C code can be reused from > languages different from Haskell. Oh, drat! I wish I had seen this earlier. Oh well. I'll see what I can pull into the ObjectIO version. It would be nice if we could use a consistent interface across both libraries. However, you have carefully factored things into Gtk/Win32 and I'm not sure if the Clean developers are interested in doing something similar. Not to be critical, but the current state of the Clean source tree is not easy to work with from a Linux/Unix environment. The main problem is that there is no main source tree that includes everything. I've had to cobble things together by downloading the source and binary copies of both the main Windows release and the Linux sources to get a full system. If there are any other interested Linux users it might make things a bit more efficient if we could create a CVS archive with the full source tree suitable for building from a Unix environment (which would include MacOS). However, I'm not trying to suggest a fork or any other "divisive" action -- I just want to make it easy for Linux users to help with some of the work... Thanks, -Brent From bfulgham@debian.org Wed, 4 Jun 2003 10:31:30 -0600 Date: Wed, 4 Jun 2003 10:31:30 -0600 From: bfulgham@debian.org bfulgham@debian.org Subject: [clean-list] More on Gtk Object IO I've made my current sources available at http://people.debian.org/~bfulgham/clean/objectio-linux.tar.gz The code compiles under Linux with Gtk-2.0 (and the associated libraries such as the Gdk, Glib, and Pango (font handling)). I think most of the basic window functionality works (buttons, check-boxes, etc.) but am running into grief with graphical programs. The current problem is with the Hanoi example. I've gzipped a tarball of this project with an apropriate Makefile and link-instruction file (gtk.lo) so that the project will build. I've reviewed the function signatures of the C bindings against the corresponding Windows stuff (in Windows_C_121) and can't see any obvious incompatibilities. However I continue to get the "Heap Full" error. I'd greatly appreciate a second (or third) pair of eyes looking at this. Thanks, -Brent From johnvg@cs.kun.nl Thu, 5 Jun 2003 12:55:12 +0200 Date: Thu, 5 Jun 2003 12:55:12 +0200 From: John van Groningen johnvg@cs.kun.nl Subject: [clean-list] More on Gtk Object IO Brent wrote: >.. >I've reviewed the function signatures of the C bindings against the >corresponding Windows stuff (in Windows_C_121) and can't see any >obvious incompatibilities. However I continue to get the "Heap Full" >error. > >I'd greatly appreciate a second (or third) pair of eyes looking at >this. The function WinDonePicture in cpicture_121.c does not return a string, because a '*' is missing before: fname = cleanstring(... After returning from WinDonePicture the string has to be copied to the Clean heap. The "Heap Full" error occurs because the length of this uninitialised string is probably very large. Regards, John van Groningen From ronny@cs.kun.nl Thu, 05 Jun 2003 15:52:38 +0200 Date: Thu, 05 Jun 2003 15:52:38 +0200 From: Ronny Wichers Schreur ronny@cs.kun.nl Subject: [clean-list] Re: Gtk ObjectIO Brent writes (to the Clean mailing list): >It would be nice if we could use a consistent interface >across both libraries. However, you have carefully >factored things into Gtk/Win32 and I'm not sure if the >Clean developers are interested in doing something >similar. > (Note: I haven't had time to look at the sources). I think it would be a good thing if the Clean and Haskell versions could share as much as possible. Is it feasible to use the same low-level interface (the OS-layer in ObjectIO)? >Not to be critical, but the current state of the Clean >source tree is not easy to work with from a Linux/Unix >environment. The main problem is that there is no >main source tree that includes everything. > We'll open our CVS tree (pserver read access) once we have some security issues sorted out. Stay tuned. Cheers, Ronny Wichers Schreur From bfulgham@debian.org Fri, 6 Jun 2003 16:52:33 -0600 Date: Fri, 6 Jun 2003 16:52:33 -0600 From: bfulgham@debian.org bfulgham@debian.org Subject: [clean-list] Clean CVS and Haskell Sharing I wrote: >It would be nice if we could use a consistent interface >across both libraries. However, you have carefully >factored things into Gtk/Win32 and I'm not sure if the >Clean developers are interested in doing something >similar. > Ronny: > (Note: I haven't had time to look at the sources). > > I think it would be a good thing if the Clean and Haskell versions could > share as much as possible. Is it feasible to use the same low-level > interface (the OS-layer in ObjectIO)? Possibly. If you were to look in the GHC CVS tree, you would see that they have a very similar structure (the basis for my effort) to the original Clean source layout. However, they changed the layout from: ../Object IO 1.2.1/OS Windows/Windows_C_121 ../Object IO 1.2.2/OS Linux/Linux_C_121 (my little area) To: ../Object IO 1.2.1/cbits/Windows (like Windows_C_121) ../Object IO 1.2.1/cbits/Linux (like my Linux_C_121) ../Object IO 1.2.1/include ../Object IO 1.2.1/graphics (like OS Windows) So, there would have to be a meeting of the minds on the proper layout. I don't know what Diederik's Cocoa stuff look like, but I found it easiest to just use the exact same interface as Windows (building whatever abstractions I needed via Gtk's facilities) rather than create an "OS Linux" directory with Gtk-specific stuff in it. I would propose doing something like: Object IO/ (the developer-level files) Object IO/OS Interface (the interface files Object IO/OS Interface/Windows_C_121 (native) Object IO/OS Interface/Linux_C_121 (native) The other problem is the way Clean passes the environment around from function-to-function. The Haskell code strips this out completely, so to be compatible we would either have to wrap each function in a Clean version (that took the environment in as arguments) which could internally call the Haskell versions. It's even harder to be compatible with Krasimir's Sourceforge work because the code has been heavily refactored into discrete units that don't map well to the current Clean source code. He can probably provide better discussion on that topic. Thanks, -Brent From bfulgham@debian.org Fri, 6 Jun 2003 16:28:10 -0600 Date: Fri, 6 Jun 2003 16:28:10 -0600 From: bfulgham@debian.org bfulgham@debian.org Subject: [clean-list] Proposed Fix Works for Gtk ObjectIO John: > > I'd greatly appreciate a second (or third) pair of eyes looking at > > this. > > The function WinDonePicture in cpicture_121.c does not return a string, > because a '*' is missing before: > > fname = cleanstring(... Thanks for catching this -- it was absolutely the right thing. Incidentally, there was also an unrelated bug due to handling of a font metric "owned" by Gtk that I fixed. With these fixes, the various programs now mostly work, though menu handling is screwed up. I intend to fix that over the next few days, then notify you all with an updated version. Thanks, -Brent From diederik@cs.kun.nl Sat, 7 Jun 2003 01:44:52 +0200 Date: Sat, 7 Jun 2003 01:44:52 +0200 From: Diederik van Arkel diederik@cs.kun.nl Subject: [clean-list] Clean CVS and Haskell Sharing On Saturday, June 7, 2003, at 12:52 AM, bfulgham@debian.org wrote: > I wrote: > >> It would be nice if we could use a consistent interface >> across both libraries. However, you have carefully >> factored things into Gtk/Win32 and I'm not sure if the >> Clean developers are interested in doing something >> similar. >> > > Ronny: >> (Note: I haven't had time to look at the sources). >> >> I think it would be a good thing if the Clean and Haskell versions >> could >> share as much as possible. Is it feasible to use the same low-level >> interface (the OS-layer in ObjectIO)? > > Possibly. If you were to look in the GHC CVS tree, you would see that > they have a very similar structure (the basis for my effort) to the > original > Clean source layout. However, they changed the layout from: > > ../Object IO 1.2.1/OS Windows/Windows_C_121 > ../Object IO 1.2.2/OS Linux/Linux_C_121 (my little area) > > To: > > ../Object IO 1.2.1/cbits/Windows (like Windows_C_121) > ../Object IO 1.2.1/cbits/Linux (like my Linux_C_121) > ../Object IO 1.2.1/include > ../Object IO 1.2.1/graphics (like OS Windows) > > So, there would have to be a meeting of the minds on the proper layout. > I don't know what Diederik's Cocoa stuff look like, but I found it > easiest to just use the exact same interface as Windows (building > whatever abstractions I needed via Gtk's facilities) rather than > create an "OS Linux" directory with Gtk-specific stuff in it. > > I would propose doing something like: > > Object IO/ (the developer-level files) > Object IO/OS Interface (the interface files > Object IO/OS Interface/Windows_C_121 (native) > Object IO/OS Interface/Linux_C_121 (native) This won't work for the Carbon bindings as the files in OS Interface are actually different. > The other problem is the way Clean passes the environment around > from function-to-function. The Haskell code strips this out > completely, > so to be compatible we would either have to wrap each function in > a Clean version (that took the environment in as arguments) which > could internally call the Haskell versions. You mean the OSToolbox parameter that gets passed to and from the C functions? This is actually unnecessary and can easily be changed. > It's even harder to be compatible with Krasimir's Sourceforge work > because the code has been heavily refactored into discrete units > that don't map well to the current Clean source code. He can probably > provide better discussion on that topic. It's probably a good idea to get Peter Achten involved as well once you have an initial version working as I know there are some changes he would like to see implemented. One of the (internal) changes I would desperately like to see is to move from a polling architecture to a callback architecture which (amongst other advantages) would allow us to remove the ugly and complex threading architecture from the C code. Regards, Diederik van Arkel (looking forward to getting the ide up and running on Linux) From ka2_mail@yahoo.com Sat, 7 Jun 2003 09:46:08 -0700 (PDT) Date: Sat, 7 Jun 2003 09:46:08 -0700 (PDT) From: Krasimir Angelov ka2_mail@yahoo.com Subject: [clean-list] Re: Clean CVS and Haskell Sharing --- bfulgham@debian.org wrote: > The other problem is the way Clean passes the > environment around > from function-to-function. The Haskell code strips > this out completely, > so to be compatible we would either have to wrap > each function in > a Clean version (that took the environment in as > arguments) which > could internally call the Haskell versions. -- Diederik van Arkel wrote: > You mean the OSToolbox parameter that gets passed to > and from the C functions? This is actually > unnecessary and can easily be changed. The OSToolbox parameter was completely removed from Haskell ObjectIO to make the library more efficient. If the parameter is not necessary for Clean (at least for low level C code) then I think it is better to remove it from there too. --- bfulgham@debian.org wrote: > It's even harder to be compatible with Krasimir's > Sourceforge work because the code has been heavily > refactored into discrete units that don't map well > to the current Clean source code. He can probably > provide better discussion on that topic. -- Diederik van Arkel wrote: > One of the (internal) changes I would desperately > like to see is to move from a polling architecture > to a callback architecture which (amongst > other advantages) would allow us to remove the ugly > and complex threading architecture from the C code. The C code from my HToolkit project is descendant of the source code from ObjectIO but it is totally rewritten to get better performance and to use the opportunities of Haskell FFI. The polling is removed and the Haskell functions use direct data marshaling instead of marshaling through CrossCallInfo structure. On this stage the HToolkit features are extended far beyond the features of ObjectIO. This is a list of its newest features: - more graphical primitives and features - the filled shapes can be filled with hatch - Join-, Cap- and LineStyle are supported for lines. - support for rotated text and shapes - better support for fonts under both Win32 and GTK. - double buffering - additional control types - ListBox - (also implemented in Haskell ObjectIO) - ProgressBar - Slider - additional standard dialogs - Multiselection open file dialog - Color selection dialog - Font selection dialog - About dialog - Message boxes - loading and writting of bitmaps in many different formats - BMP, JPG, PNG, GIF ... - the application can create and edit bitmaps in memory. - extended functionality for menus - support for radio and checked menu items. The radio items and checked items in ObjectIO have the same look, while in the HToolkit they have the native look and feel for the platform. - Bitmaped menu items - for each item a bitmap can be assigned and it will be displayed to the left of the item text. - Any key can be used as accelerator for each menu item, while in the ObjectIO it is limited to Ctrl+ Still missing but planed features: - Support for ToolBar - Support for drag & drop from Windows Explorer to application. If you have serious intentions to port ObjectIO to Linux then I think it is a good idea to discuss the posibilities of developing API for both Haskell and Clean. I complettely agree that it is hard to make ObjectIO to work with HToolkit API but if this happens one day then you will be able to use the advantages of HToolkit. The greatest advantage of this idea is that we can share the work for library development. Best regards, Krasimir Angelov __________________________________ Do you Yahoo!? Yahoo! Calendar - Free online calendar with sync to Outlook(TM). http://calendar.yahoo.com From bfulgham@debian.org Sat, 07 Jun 2003 11:58:48 -0700 Date: Sat, 07 Jun 2003 11:58:48 -0700 From: Brent A. Fulgham bfulgham@debian.org Subject: [clean-list] Examples Available For fun, I put a status page up at http://people.debian.org/~bfulgham/clean_examples It shows the current programs (in their partially working state). -Brent From shiv@ece.ucsb.edu Thu, 12 Jun 2003 18:38:14 -0700 Date: Thu, 12 Jun 2003 18:38:14 -0700 From: Shivkumar Chandrasekaran shiv@ece.ucsb.edu Subject: [clean-list] Class restriction to 32 I am coming back to clean for the first time after 1.3 was released. In 1.3 there was a "restriction" to a maximum of 32 entries for a class. Has that restriction been lifted in 2.0? Thanks, --shiv-- From pieter@cs.kun.nl Fri, 13 Jun 2003 11:11:20 +0200 Date: Fri, 13 Jun 2003 11:11:20 +0200 From: Pieter Koopman pieter@cs.kun.nl Subject: [clean-list] Class restriction to 32 At 18:38 12-06-2003 -0700, Shivkumar Chandrasekaran wrote: >I am coming back to clean for the first time after 1.3 was released. In >1.3 there was a "restriction" to a maximum of 32 entries for a class. Has >that restriction been lifted in 2.0? No, keep 32 as a the maximum number of fields in a record. Although it might work correctly in small examples for larger records (by accident). Have fun, Pieter Koopman From shiv@ece.ucsb.edu 13 Jun 2003 09:07:07 -0700 Date: 13 Jun 2003 09:07:07 -0700 From: shivkumar chandrasekaran shiv@ece.ucsb.edu Subject: [clean-list] Re: Class restriction to 32 > No, keep 32 as a the maximum number of fields in a record. Although it > might work correctly in small examples for larger records (by accident). > > Have fun, > > Pieter Koopman My problem is not that I *explicitly* create records or classes with more than 32 entries in them. Rather it is the fact that I have lots of classes, more than 32, and I write functions that utilize more than 32 of these classes, mostly indirectly. Clean 1.3 used to barf on such cases. My question is, does this continue to be the case in 2.0? This is not an idle question. I already have an interface to LAPACK and BLAS in OCaml, that lets me write a single code that works in real double, real single, complex double and complex single precisions. In OCaml I achieve this by using functors. Since Clean does not have functors, I am trying to achieve the same thing by using classes. Is there any other way to do this? Thanks for your time. --shiv-- PS: Let me try to build a mock example here of what I mean: class ci t } instance ci Real } where i goes from 1 to 100 say instance ci Complex } Then I define some utility functions fun_i _ _ _ | ci_1, ci_2, ... ci_10 And suppose there are 50 such utility functions, all of which depend on 10 classes individually. Now suppose I build my big function g _ _ _ | fun_1, fun_2, fun_3, fun_4, fun_5 Now g indirectly depends on more than 32 class members. In 1.3 I remember this being a problem. Will this work in 2.0? If not, is there a way around it? From dvanarkel@mac.com Fri, 13 Jun 2003 23:00:51 +0200 Date: Fri, 13 Jun 2003 23:00:51 +0200 From: Diederik van Arkel dvanarkel@mac.com Subject: [clean-list] Re: Class restriction to 32 On Friday, June 13, 2003, at 06:07 PM, shivkumar chandrasekaran wrote: [snip] > PS: Let me try to build a mock example here of what I mean: > > class ci t } > instance ci Real } where i goes from 1 to 100 say > instance ci Complex } > > Then I define some utility functions > > fun_i _ _ _ | ci_1, ci_2, ... ci_10 > > And suppose there are 50 such utility functions, all of which depend on > 10 classes individually. > > Now suppose I build my big function > > g _ _ _ | fun_1, fun_2, fun_3, fun_4, fun_5 > > Now g indirectly depends on more than 32 class members. In 1.3 I > remember this being a problem. Will this work in 2.0? If not, is there > a > way around it? I'd guess that you will still run into the same problems. Have you tried defining a class combining the individual classes you require e.g. class Combined a | ci_1,ci_2,ci_3,...,ci_10 a and then having your function typed as fun :: ... | Combined a I believe this should allow you to reduce the number of function arguments below 32 again. Note that you are really running into two restrictions here. One that classes are restricted to 32 members and the other that functions are restricted to 32 arguments including class restrictions. HTH Diederik van Arkel From shiv@ece.ucsb.edu 13 Jun 2003 14:37:37 -0700 Date: 13 Jun 2003 14:37:37 -0700 From: shivkumar chandrasekaran shiv@ece.ucsb.edu Subject: [clean-list] Re: Class restriction to 32 On Fri, 2003-06-13 at 14:00, Diederik van Arkel wrote: > I'd guess that you will still run into the same problems. Have you > tried defining > a class combining the individual classes you require e.g. > > class Combined a | ci_1,ci_2,ci_3,...,ci_10 a > > and then having your function typed as > > fun :: ... | Combined a > > I believe this should allow you to reduce the number of function > arguments below > 32 again. Note that you are really running into two restrictions here. > One that classes > are restricted to 32 members and the other that functions are > restricted to 32 arguments > including class restrictions. > > HTH > > Diederik van Arkel Thanks. I didn't realize this double restriction existed. Since nested Class definitions don't add up that should solve my problem. Maybe I can stick these useless Combined class definitions at the end of the file somewhere :) It would be nice if the next version of the Clean compiler would either complain about it, or handle it internally. Great, that helped a lot. Now to try it all out ... . --shiv-- PS: It would be nice to have these implementation-dependent restrictions and current outstanding bugs available publicly somewhere. From gkoller@inter.nl.net Mon, 16 Jun 2003 11:41:10 +0200 Date: Mon, 16 Jun 2003 11:41:10 +0200 From: Guido Kollerie gkoller@inter.nl.net Subject: [clean-list] ICFP 2003 programming contest --SLDf9lqlvOQaIe6s Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable FYI, The ICFP 2003 programming contest will start in two weeks time. http://www.dtek.chalmers.se/groups/icfpcontest/ When the winners are announced it tends to be covered on Slashdot.org, bringing the winning team/language combo under the attention of a large public. Last year the results were: 1. Ocaml 2. C 3. Python ICFP 2002 website: =20 http://icfpcontest.cse.ogi.edu/ The last time a Clean entry was submitted was in 2000: =20 http://www.cs.cornell.edu/icfp/contest_results.htm --=20 Guido --SLDf9lqlvOQaIe6s Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.2 (FreeBSD) iEYEARECAAYFAj7tkLYACgkQC7vo05+GQSzZJwCeIUa+sDm4IPX154IXTe3lKkcN cTEAnAn2uzI6YNQphnWEDjdPIP8Oj1I7 =ihCi -----END PGP SIGNATURE----- --SLDf9lqlvOQaIe6s-- From shiv@ece.ucsb.edu Mon, 16 Jun 2003 10:11:21 -0700 Date: Mon, 16 Jun 2003 10:11:21 -0700 From: Shivkumar Chandrasekaran shiv@ece.ucsb.edu Subject: [clean-list] Unboxed 2D arrays I noticed that the Clean 2.* compiler accepts the following type definition: :: *Matrix t :== *{#{#t}} Does this mean that Matrix Int for example will be stored in row-major order, since the un-boxing requests seems to be honored? Or, is this a bug? Thanks, --shiv-- From alanh@dcs.kcl.ac.uk Fri, 20 Jun 2003 22:00:55 +0100 (BST) Date: Fri, 20 Jun 2003 22:00:55 +0100 (BST) From: alanh@dcs.kcl.ac.uk alanh@dcs.kcl.ac.uk Subject: [clean-list] ObjectIO test of Identifiers etc If anyone cares to ofer advice, it will be welcome. Below is my first attempt to write a Clean program with ObjectIO which actually does something. What it actually does is not what any good program should do. This is an experiment with one window, one button control, and two menus. It was compiled and run with Clean 2.0.2 and ObjectIO 1.2.3 under Microsoft Windows XP. The button works. The first menu is Unable when started, as intended. The second menu contains two elements: - element 1 quits the program. It works. - element 2 should toggle whether menu 1 is Able or Unable. When it is clicked, the whole window ceases to work. The entire menu bar disappears. The cursor turns into an hourglass. A DOS window appears (although the program was not configured with one), with a message to press any key to stop the program. If this is minimised, a message appears on the main program's window saying that it is not responding. What have I done wrong? Alan Hutchinson Dept. of Computer Science King's College London ----------------------------- module wmitest import StdEnv, StdIO Start :: *World -> *World Start w0 = startIO SDI Void initialise [] w1 where (menu01Id, w1) = openId w0 initialise pst # (error, pst) = openWindow Void mainwindow pst | error <> NoError = abort "Couldn't open the main window." # (error, pst) = openMenu Void menu01 pst | error <> NoError = abort "Couldn't open Menu 01." # (error, pst) = openMenu Void menu02 pst | error <> NoError = abort "Couldn't open Menu 02." | otherwise = pst mainwindow = Window "Window - Menu - Identifier test" maincontrols [(WindowClose (noLS closeProcess)) ] maincontrols = ButtonControl "Quit" [ControlFunction (noLS closeProcess)] menu01 = Menu "Menu 01" (MenuItem "Quit 01" [MenuFunction (noLS closeProcess)]) [MenuId menu01Id ,MenuSelectState Unable] menu02 = Menu "Menu 02" (MenuItem "Quit 02" [MenuFunction (noLS closeProcess) ,MenuShortKey 'q' // really means 'q' but is displayed as 'Ctrl+Q' ! ] :+: MenuItem "toggle Menu 01" [MenuFunction (noLS (toggleMenu menu01Id))] ) [] toggleMenu :: Id (PSt .l) -> PSt .l toggleMenu id pst | isNothing maybeMstate = abort "A menu's Id doesn't refer to a menu." | not tf = abort "Can't get a menu's select state." | selectState == Able = {pst & io = disableMenuElements [id] io2} | otherwise = {pst & io = enableMenuElements [id] io2} where (maybeMstate, io2) = getMenu id pst.io (Just mState) = maybeMstate (tf, selectState) = getMenuElementSelectState id mState From vanarkel@knoware.nl Sat, 21 Jun 2003 00:09:36 +0200 Date: Sat, 21 Jun 2003 00:09:36 +0200 From: Diederik van Arkel vanarkel@knoware.nl Subject: [clean-list] ObjectIO test of Identifiers etc On Friday, June 20, 2003, at 11:00 PM, wrote: > If anyone cares to ofer advice, it will be welcome. > Below is my first attempt to write a Clean program with ObjectIO > which actually does something. What it actually does is not what > any good program should do. > > This is an experiment with one window, one button control, and > two menus. It was compiled and run with Clean 2.0.2 and ObjectIO 1.2.3 > under Microsoft Windows XP. > > The button works. > > The first menu is Unable when started, as intended. > > The second menu contains two elements: > - element 1 quits the program. It works. > - element 2 should toggle whether menu 1 is Able or Unable. > When it is clicked, the whole window ceases to work. > The entire menu bar disappears. > The cursor turns into an hourglass. > A DOS window appears (although the program was not configured > with one), with a message to press any key to stop the program. > If this is minimised, a message appears on the main program's > window saying that it is not responding. > > What have I done wrong? Hi Alan, actually ObjectIO is also displaying your "Can't get a menu's select state." abort message, either in a window somewhere or in your Messages file depending on your project settings. This is because you are mixing up Menus and MenuElements. You want to be using enableMenus,disableMenus, and getMenuSelectState rather than their MenuElement versions. HTH Diederik van Arkel From alanh@dcs.kcl.ac.uk Tue, 8 Jul 2003 09:39:11 +0100 Date: Tue, 8 Jul 2003 09:39:11 +0100 From: Alan Hutchinson alanh@dcs.kcl.ac.uk Subject: [clean-list] Object IO queries Here are three queries about windows in the OBJECT IO library. They arise when my Clean program is compiled and run under Microsoft Windows XP. 1 The standard red X button at the top right of a window's title bar, which closes windows of most programs, seems not to work. Can it be made to work? It does not matter as long as the window has some other means of being closed, such as a working "Quit" item in a "File" menu. 2 The default size for a new window is the whole screen, but this causes some of it to be obscured by the MS WXP status bar at the bottom. Thus, any control at position LeftBottom is partly hidden. 3 Is there a way to alter the choice of set of controls in a window after the window has been opened? I would like to add and remove various controls as the program's user works through its actions, but I cannot see how to do it. The alternative is to open a set of windows, one for each choice of set of controls, and make the appropriate window active each time the set of visible controls should change. This should work, but it seems rather elaborate since each window requires a separate process, and the contents, positions and looks of corresponding controls in different windows have to be matched. With thanks for any suggestions Alan -- Alan Hutchinson Department of Computer Science King's College London Strand London WC2R 2LS alanh@dcs.kcl.ac.uk From peter88@cs.kun.nl Thu, 10 Jul 2003 09:31:59 +0200 Date: Thu, 10 Jul 2003 09:31:59 +0200 From: Peter Achten peter88@cs.kun.nl Subject: [clean-list] Object IO queries --=====================_2949327==_.ALT Content-Type: text/plain; charset="us-ascii"; format=flowed At 09:39 8-7-03 +0100, Alan Hutchinson wrote: >Here are three queries about windows in the OBJECT IO library. >They arise when my Clean program is compiled and run under >Microsoft Windows XP. > >1 The standard red X button at the top right of a window's title bar, > which closes windows of most programs, seems not to work. > Can it be made to work? > It does not matter as long as the window has some other means of > being closed, such as a working "Quit" item in a "File" menu. Clicking the X button of a window only causes an event to be sent to the window. The window then can deside if it should close or not. Therefore, the default behaviour of a window is not to close. If you want a window to close in all cases, you can add the following WindowAttribute to its attribute-list: Window title controls [ WindowClose (noLS closeActiveWindow) : other attributes ] However, if you open this window in a SDI process then the X button that you see does not belong to the window but rather to its parent process. Clicking this button sends a similar event to the parent process, and you should a similar line to the process attribute list. If you want the parent process to close the window when this button is closed, use: Process xDI state initGUI [ ProcessClose closeActiveWindow : other attributes ] or, if it should close the process itself: Process xDI state initGUI [ ProcessClose closeProcess : other attributes ] If you want a combined behaviour, then you should keep track of open windows or ask the system (e.g. using getWindowStack or getWindowsStack). >2 The default size for a new window is the whole screen, but this > causes some of it to be obscured by the MS WXP status bar at the bottom. > Thus, any control at position LeftBottom is partly hidden. This is a known bug for windows with unspecified initial sizes in SDI processes. I will see if I can fix it in a next release of Object I/O. >3 Is there a way to alter the choice of set of controls in a window after > the window has been opened? I would like to add and remove various > controls as the program's user works through its actions, but I cannot see > how to do it. > The alternative is to open a set of windows, one for each choice of set > of controls, and make the appropriate window active each time the set of > visible controls should change. This should work, but it seems > rather elaborate since each window requires a separate process, and the > contents, positions and looks of corresponding controls in different > windows have to be matched. All GUI elements in Object I/O can be created dynamically as well as closed dynamically. For opening controls you can use one of: openControls, openCompoundControls, openPopUpControlItems. For closing controls you can use one of: closeControls, closeAllControls, closePopUpControlItems. Regards, Peter --=====================_2949327==_.ALT Content-Type: text/html; charset="us-ascii" At 09:39 8-7-03 +0100, Alan Hutchinson wrote:
Here are three queries about windows in the OBJECT IO library.
They arise when my Clean program is compiled and run under
Microsoft Windows XP.

1  The standard red X button at the top right of a window's title bar,
   which closes windows of most programs, seems not to work.
   Can it be made to work?
   It does not matter as long as the window has some other means of
   being closed, such as a working "Quit" item in a "File" menu.
Clicking the X button of a window only causes an event to be sent to the window. The window then can deside if it should close or not. Therefore, the default behaviour of a window is not to close. If you want a window to close in all cases, you can add the following WindowAttribute to its attribute-list:
Window title controls
   [ WindowClose (noLS closeActiveWindow)
    : other attributes
   ]

However, if you open this window in a SDI process then the X button that you see does not belong to the window but rather to its parent process. Clicking this button sends a similar event to the parent process, and you should a similar line to the process attribute list. If you want the parent process to close the window when this button is closed, use:
Process xDI state initGUI
   [ ProcessClose closeActiveWindow
    : other attributes
   ]

or, if it should close the process itself:
Process xDI state initGUI
   [ ProcessClose closeProcess
    : other attributes
   ]

If you want a combined behaviour, then you should keep track of open windows or ask the system (e.g. using getWindowStack or getWindowsStack).

2 The default size for a new window is the whole screen, but this
   causes some of it to be obscured by the MS WXP status bar at the bottom.
   Thus, any control at position LeftBottom is partly hidden.
This is a known bug for windows with unspecified initial sizes in SDI processes. I will see if I can fix it in a next release of Object I/O.

3  Is there a way to alter the choice of set of controls in a window after
   the window has been opened?  I would like to add and remove various
   controls as the program's user works through its actions, but I cannot see
   how to do it.
   The alternative is to open a set of windows, one for each choice of set
   of controls, and make the appropriate window active each time the set of
   visible controls should change.  This should work, but it seems
   rather elaborate since each window requires a separate process, and the
   contents, positions and looks of corresponding controls in different
   windows have to be matched.
All GUI elements in Object I/O can be created dynamically as well as closed dynamically. For opening controls you can use one of: openControls, openCompoundControls, openPopUpControlItems. For closing controls you can use one of: closeControls, closeAllControls, closePopUpControlItems.

Regards,
Peter
--=====================_2949327==_.ALT-- From bfulgham@debian.org Tue, 15 Jul 2003 23:30:22 -0700 Date: Tue, 15 Jul 2003 23:30:22 -0700 From: Brent A. Fulgham bfulgham@debian.org Subject: [clean-list] CVS Status Hi, I was curious if there was any news on the CVS archive? I've been hoping to work on my changes from withing a "global" source pool (rather than hand-copying the files from the Windows and Linux distributions to make my local build.) Thanks, -Brent From divianp@delfin.unideb.hu Tue, 22 Jul 2003 16:19:16 +0200 (DFT) Date: Tue, 22 Jul 2003 16:19:16 +0200 (DFT) From: Divianszky Peter divianp@delfin.unideb.hu Subject: [clean-list] overloading problem Hi, I have met a strange overloading problem in Clean: import StdEnv class C a | zero a where c1 :: a c2 :: (a -> a) instance zero [a] | zero a where zero = ... instance C [a] where c1 = [] c2 = f where f _ = c1 => error "internal overloading of f could not be solved" This is just a minimal illustration and can be solved in various ways but I have more serious examples too. I think it always helps when I specify the type of f. (I don't understand why is it necessary!) In my case it is not a good idea; I am working on the Haskell interface. Please help me! Peter Divianszky From ronny@cs.kun.nl Thu, 24 Jul 2003 16:03:11 +0200 Date: Thu, 24 Jul 2003 16:03:11 +0200 From: Ronny Wichers Schreur ronny@cs.kun.nl Subject: [clean-list] overloading problem Peter Divianszky writes (to the Clean list): >I have met a strange overloading problem in Clean: >[..] > class C a | zero a where >[..] > 1) instances of (C a) need an instance of (zero a) > instance zero [a] | zero a where zero = ... > 2) Given an instance of (zero a) this makes an instance (zero [a]) > instance C [a] where >[..] > By 1) this means that you need an instance (zero [a]), but how should this be obtained? So >=> error "internal overloading of f could not be solved" > >[..] > If an instance of (zero a) would be available the compiler could use 2) to get the instance (zero [a]) that's needed for the instance (C [a]). In Clean: instance C [a] | zero a where ... >In my case it is not a good idea; I am working on the Haskell interface. > You'd have the same problem in Haskell, but ghc's error message is much more helpful: Could not deduce (Zero a) from the context () arising from the instance declaration at t.hs:12 Probable fix: Add (Zero a) to the instance declaration superclass context In the instance declaration for `C [a]' Ronny Wichers Schreur From ronny@cs.kun.nl Thu, 24 Jul 2003 16:35:06 +0200 Date: Thu, 24 Jul 2003 16:35:06 +0200 From: Ronny Wichers Schreur ronny@cs.kun.nl Subject: [clean-list] Re: CVS Status Brent A. Fulgham writes (to the Clean list) >I was curious if there was any news on the CVS archive? > The anonymous cvs server is up and running at :pserver:anonymous@cvs-srv.cs.kun.nl:/clean (empty password). What's there now: CleanTools/ (Clean IDE) compiler/ (Clean compiler) dynamic/ (Linkers and dynamic support (Windows)) libraries/ObjectIO (ObjectIO library) Things I plan to do in the next two weeks: - reorganise a bit; - automate sync between our live repository and the public repository; - add missing libraries from the Clean distribution; - describe modules and tags; - enable web browsing for the public repository. So you're welcome to use the repository now, but it hasn't fully stabilised yet. Cheers, Ronny Wichers Schreur From divip@freemail.hu Mon, 28 Jul 2003 11:49:38 +0200 (CEST) Date: Mon, 28 Jul 2003 11:49:38 +0200 (CEST) From: Divianszky Peter divip@freemail.hu Subject: [clean-list] overloading problem & compiler crash --0-1804289383-1059385778=:35965 Content-Type: TEXT/PLAIN; CHARSET=ISO-8859-2 Thank you Ronny, with your explanation I could solve my overloading problem. Now I have a small project, the Clean 2.0.2 compiler crashes on it with the error "index out of range" (you can find it in the attachment too): module test import Prelude Start = 1 definition module Prelude import StdEnv zero``` :: Int zero`` :== zero` zero` :: a | zero a implementation module Prelude import StdEnv zero``` :: Int zero``` = zero`` zero`` :== zero` zero` :: a | zero a zero` = zero Peter --0-1804289383-1059385778=:35965 Content-Type: APPLICATION/zip; name="error.zip" Content-Transfer-Encoding: BASE64 Content-Disposition: attachment; filename="error.zip" UEsDBBQAAgAAAFkL+S4AAAAAAAAAAAAAAAAMAAAAbWFjcm9fZXJyb3IvUEsD BBQAAgAIAOW0+C7Myu18UQAAAGkAAAAXAAAAbWFjcm9fZXJyb3IvUHJlbHVk ZS5kY2xLSU3LzMssyczPU8jNTynNSVUIKErNKU1J5eXi5crMLcgvKlEILklx zSsDCVSlFuUnJCQoWFkpeOaVIEQUrGxtFcBMuBhITaJCDVhUIZGXCwBQSwME FAACAAgAFbX4LismMBVfAAAAkQAAABcAAABtYWNyb19lcnJvci9QcmVsdWRl LmljbMvMLchJzU3NK0ksyczPU8jNTynNSVUIKErNKU1J5eXi5crMLcgvKlEI LklxzSsDCVSlFuUnJCQoWFkpeOaVIPi2ChAWQo2ClS1UEC4G0pWoUAMWVUiE CUJUgRTxcgEAUEsDBBQAAgAIAHQL+S5vJoFlKgAAACoAAAAUAAAAbWFjcm9f ZXJyb3IvdGVzdC5pY2zLzU8pzUlVKEktLuHl4uXKzC3ILypRCChKzSlNSeXl Ci5JBHJtFQx5uQBQSwMEFAACAAgA/Av5LjcOFWlaAgAARQUAABQAAABtYWNy b19lcnJvci90ZXN0LnByaq1U204bMRB9XiT+gS9AC00r2LewBBopG1CSQiv1 xdkdiInX3o7HNLTqv3dss1lDX6tIieec8ZmrcwdopdHF0cnx6PDgWpm1UIcH 2YWTiorsSigLbK4EPgLbS2om+pmByQ7qIvt9i+YJavrzncDSMey8b2kauAbN p6zcQL1dkqi3dtCK6FQ37M7wCl1AYwgWrMFag0VWOkTQA8JO465TshbECfsr n0F0S/kLimyUn3/Kc4+FaBE8yU9HEZzsCEUFrcGXIjs7OT8N6FSTFGoQOc1H Z9G/xyqnSHJIwBgiBNiYn75657NYyRaSyjx3Xb4Dkoz2eCVwK/VjaZTi9vlq hyskdCOwWThOrwVu99Aj7sWDVOGY9eXsL74ildSyde1QVqgoe5dp7FMC3Djq HAUqHouQfGm0JXQ+RxvIK6OZKo1D7soeiZHOg32PksAvCiZlzaTeetb/VkAb 0/hl4knWHuV1ARQEC1Amjjfdl54Nd0WXMB5ZgOVkakhv9NgyfBdZqnI5myWe k11nkKCZi9YrMHQraBNK9YdkxT2FUJu24wlET2NJcQbeqITUlWlcGI4XKzL/ JNi4lPhWpYwSoXlzeAaMc3udbZJbIP3c/qWWhLImze9irIV6sTJ5SDNpafXS +XKiW6wxQD0/JmbWjtIHeC9Q804myB3g2lgYgAWIRqwVjC/KN912Fr5o+cPB nN/+IHBZqyAsdWN+crdk/3Czr/1afusPfoMY/ZgPJnMfgsk6Nx3oIeT0PwlP e+HXhGfCEk9RPkjg/Zybo3z4HB7s95X/hm7jBuBTOPwFUEsBAhQAFAACAAAA WQv5LgAAAAAAAAAAAAAAAAwAAAAAAAAAAAAwAAAAAAAAAG1hY3JvX2Vycm9y L1BLAQIUABQAAgAIAOW0+C7Myu18UQAAAGkAAAAXAAAAAAAAAAAAIAAAACoA AABtYWNyb19lcnJvci9QcmVsdWRlLmRjbFBLAQIUABQAAgAIABW1+C4rJjAV XwAAAJEAAAAXAAAAAAAAAAAAIAAAALAAAABtYWNyb19lcnJvci9QcmVsdWRl LmljbFBLAQIUABQAAgAIAHQL+S5vJoFlKgAAACoAAAAUAAAAAAAAAAAAIAAA AEQBAABtYWNyb19lcnJvci90ZXN0LmljbFBLAQIUABQAAgAIAPwL+S43DhVp WgIAAEUFAAAUAAAAAAAAAAAAIAAAAKABAABtYWNyb19lcnJvci90ZXN0LnBy alBLBQYAAAAABQAFAEgBAAAsBAAAAAA= --0-1804289383-1059385778=:35965-- From brent.fulgham@xpsystems.com Tue, 29 Jul 2003 17:29:08 -0700 Date: Tue, 29 Jul 2003 17:29:08 -0700 From: Brent Fulgham brent.fulgham@xpsystems.com Subject: [clean-list] Update on ObjectIO (GTK+) Effort Diederik has been a huge help in getting the fledgling Gtk+ port of ObjectIO to work. But he alone can't field the many stupid questions and please for help from yours truly! So, I'd like to make a public plea for other Linux users to get involved in the porting effort. You can get an idea of where we stand by visiting my little progress page: (http://people.debian.org/~bfulgham/clean_examples). Many things are working, many things are not. Choose something that doesn't work and see if you can provide any insight! Sources are located at http://people.debian.org/~bfulgham/clean. Distribution is a bit of a mess right now, so you may want to retrieve the sources from CVS and just use the Linux_C_12.tar.gz file from my web site to get the "current" version. Thanks, -Brent From divianp@delfin.unideb.hu Fri, 1 Aug 2003 18:44:03 +0200 (DFT) Date: Fri, 1 Aug 2003 18:44:03 +0200 (DFT) From: Divianszky Peter divianp@delfin.unideb.hu Subject: [clean-list] compiler crash again I tried my previous crash project with the compiler downloaded this week with cvs, but the result is the same "index out of range" during the compilation. I think this error could be fixed easily, because when I change the order of lines in the dcl file, everything seems ok. Please help me fixing the bug, Peter > Now I have a small project, the Clean 2.0.2 compiler crashes > on it with the error "index out of range" > (you can find it in the attachment too): > > module test > import Prelude > Start = 1 > > definition module Prelude > import StdEnv > zero``` :: Int > zero`` :== zero` > zero` :: a | zero a > > implementation module Prelude > import StdEnv > zero``` :: Int > zero``` = zero`` > zero`` :== zero` > zero` :: a | zero a > zero` = zero > > > Peter > From bfulgham@gluck.debian.org Tue, 5 Aug 2003 11:08:07 -0600 Date: Tue, 5 Aug 2003 11:08:07 -0600 From: Brent A. Fulgham bfulgham@gluck.debian.org Subject: [clean-list] Building Clean from Source (Win32) I have no problems building the Linux version of Clean. But when I retrieve the CVS sources I can't figure out how to build the corresponding Windows version. Are there any instructions on how to build ObjectIO under Windows? It seems like there should be some project files in the archive that can be used to drive the build. Are these stored elsewhere? Thanks, -Brent From vanarkel@knoware.nl Tue, 5 Aug 2003 23:16:00 +0200 Date: Tue, 5 Aug 2003 23:16:00 +0200 From: Diederik van Arkel vanarkel@knoware.nl Subject: [clean-list] Building Clean from Source (Win32) On Tuesday, August 5, 2003, at 07:08 PM, Brent A. Fulgham wrote: > I have no problems building the Linux version of Clean. But when I > retrieve the CVS sources I can't figure out how to build the > corresponding Windows version. > > Are there any instructions on how to build ObjectIO under Windows? It > seems like there should be some project files in the archive that can > be > used to drive the build. Are these stored elsewhere? > > Thanks, > > -Brent Not sure what you mean here. The ObjectIO in CVS is ready to use as is, no building required. The only extra work involved is when you start modifying the *.c sources. These are compiled with VisualC and the resulting object files are saved in ObjectIO\OSWIndows\Clean System Files\ I used the commandline visual c compiler or a project setup with the correct paths depending on my mood. Neither of these should be too difficult to set up. Regards, Diederik van Arkel From willeralves@yahoo.com.br Wed, 6 Aug 2003 15:07:54 -0300 (ART) Date: Wed, 6 Aug 2003 15:07:54 -0300 (ART) From: =?iso-8859-1?q?Alves=20da=20Silva=20Cruz=20Willer?= willeralves@yahoo.com.br Subject: [clean-list] Treating Wave files and FFT --0-1166205831-1060193274=:27294 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit Hello all! I'm starting the implementation of a program that reads and plots the waveform stored in a Wave file using Object IO. As you now, wave files are huge. The program is working but it is a lot slow. As I'm thinking of implementing ChirpZ and FFT algorithms to be applied in this waveform, I think the speed of execution will not be acceptable this way in the final program. I'm using Real lists by the moment, but I'm thinking of changing it to Arrays. But I don't know if I will gain performance improvement once the program will be still very recursive. Has someone tried to work with large amount of data using Clean? How could be the best form to deal with it? Thanks in advance. Willer Alves Uberlândia, MG - Brazil --------------------------------- Conheça o novo Cadê? - Mais rápido, mais fácil e mais preciso. Toda a web, 42 milhões de páginas brasileiras e nova busca por imagens! --0-1166205831-1060193274=:27294 Content-Type: text/html; charset=iso-8859-1 Content-Transfer-Encoding: 8bit
Hello all!
 
I'm starting the implementation of a program that reads and plots the waveform stored in a Wave file using Object IO. As you now, wave files are huge. The program is working but it is a lot slow. As I'm thinking of implementing ChirpZ and FFT algorithms to be applied in this waveform, I think the speed of execution will not be acceptable this way in the final program. I'm using Real lists by the moment, but I'm thinking of changing it to Arrays. But I don't know if I will gain performance improvement once the program will be still very recursive.
 
Has someone tried to work with large amount of data using Clean? How could be the best form to deal with it?
 
Thanks in advance.
 
Willer Alves
Uberlândia, MG - Brazil



Conheça o novo Cadê? - Mais rápido, mais fácil e mais preciso.
Toda a web, 42 milhões de páginas brasileiras e nova busca por imagens! --0-1166205831-1060193274=:27294-- From vissers@theochem.kun.nl Fri, 22 Aug 2003 16:33:27 +0200 (CEST) Date: Fri, 22 Aug 2003 16:33:27 +0200 (CEST) From: G.W.M. Vissers vissers@theochem.kun.nl Subject: [clean-list] Problem overloading <<< for lists Hello all, I'm trying to implement writing a list to file, and I want the behaviour to depend on the type of the elements in the list, like: module tst import StdFile instance <<< [Int] where (<<<) :: !*File ![Int] -> !*File (<<<) f _ = f instance <<< [Real] where (<<<) :: !*File ![Real] -> !*File (<<<) f _ = f Start :: !*World -> *World Start world # (cons, world) = stdio world # cons = cons <<< [1,2,3] <<< "\n" # (ok, world) = fclose cons world = world Trying to compile this gives (Clean 2.0.2, Linux x86) Error [tst.icl,5,<<<]:multiply defined So it looks like the compiler ignores the type of the list elements. Does anyone have a clue as to how to resolve this? (apart from introducing a new, abstract type, I mean) Thanks, Gé From a.v.w@hccnet.nl Fri, 22 Aug 2003 15:24:52 UT Date: Fri, 22 Aug 2003 15:24:52 UT From: a.v.w@hccnet.nl a.v.w@hccnet.nl Subject: [clean-list] Problem overloading <<< for lists This is a multi-part message in MIME format. --_----------=_106156589298066 Content-Disposition: inline Content-Length: 1698 Content-Transfer-Encoding: binary Content-Type: text/plain Hello Ge, In Clean instances must all be different at the outermost type. Both instances in your example are lists, hence the error. Very annoying, I agree. I usually solve this by introducing a new class (instead of a new type) for the outermost type (lists, in this case, often it's arrays). I think the compiler could do this automatically, if someone implemented it. class writeList a :: !*File ![a] -> *File instance writeList Int //your code for instance <<< [Int] instance writeList Real //your code for instance <<< [Real] instance <<< [a] | instance writeList a where (<<<) f list = writelist f list regards, Arjen > > Hello all, > > I'm trying to implement writing a list to file, and I want the behaviour > to depend on the type of the elements in the list, like: > > module tst > > import StdFile > > instance <<< [Int] > where > (<<<) :: !*File ![Int] -> !*File > (<<<) f _ = f > > instance <<< [Real] > where > (<<<) :: !*File ![Real] -> !*File > (<<<) f _ = f > > Start :: !*World -> *World > Start world > # (cons, world) = stdio world > # cons = cons <<< [1,2,3] <<< "\n" > # (ok, world) = fclose cons world > = world > > > Trying to compile this gives (Clean 2.0.2, Linux x86) > > Error [tst.icl,5,<<<]:multiply defined > > So it looks like the compiler ignores the type of the list elements. > Does anyone have a clue as to how to resolve this? (apart from > introducing > a new, abstract type, I mean) > > Thanks, > > Gé > > > > _______________________________________________ > clean-list mailing list > clean-list@cs.kun.nl > http://www.cs.kun.nl/mailman/listinfo/clean-list --_----------=_106156589298066-- From greenrd@greenrd.org Sun, 24 Aug 2003 01:57:54 +0100 Date: Sun, 24 Aug 2003 01:57:54 +0100 From: Robin Green greenrd@greenrd.org Subject: [clean-list] Clean 1.3.1 license and htoclean 1.0 I have two questions relating to htoclean 1.0 for Linux. 1. The download page says htoclean is a clean 1.3 add on, but I downloaded clean 1.3.1 for Linux and it still had the old non-LGPL license conditions included in the .tar.gz file. Would it be possible to release clean 1.3.1 under a Free Software license or dual license? If not, I will try to use htoclean with Clean 2.0. Which leads to the question... 2. What license is htoclean 1.0 under? (And the other clean 1.3 libraries?) -- Robin From byron.hale@einfo.com Thu, 28 Aug 2003 20:05:48 -0700 Date: Thu, 28 Aug 2003 20:05:48 -0700 From: Byron Hale byron.hale@einfo.com Subject: [clean-list] Version confusion When I install Clean 2.0.2 and run Clean, I get a version of 2.0.1.42 (when consulting Help/About). What should the version be? Byron Hale byron.nospam.hale@einfo.com From igouy@yahoo.com Fri, 29 Aug 2003 13:22:15 -0700 (PDT) Date: Fri, 29 Aug 2003 13:22:15 -0700 (PDT) From: isaac gouy igouy@yahoo.com Subject: [clean-list] data structures for destructive update Is there a way to destructively update the contents of array item.val, without creating a new item record? i = {key="a", val=toCell(5)} // do update // contents of array i.val is now 7 :: Item a = { key::!String , val::a } toCell:: a -> *{a} toCell val = {val} best wishes, Isaac __________________________________ Do you Yahoo!? Yahoo! SiteBuilder - Free, easy-to-use web site design software http://sitebuilder.yahoo.com From willeralves@yahoo.com.br Fri, 29 Aug 2003 17:19:35 -0300 (ART) Date: Fri, 29 Aug 2003 17:19:35 -0300 (ART) From: =?iso-8859-1?q?Alves=20da=20Silva=20Cruz=20Willer?= willeralves@yahoo.com.br Subject: [clean-list] stdScrollFunction --0-1478827110-1062188375=:33322 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit I'm getting in some troubles using stdScrollFunction. When I use it, it does the scrolling, but the screen is not actually updated in the new area. So, I'm getting a confused image when I do the scrolling. What am I supposed to do? Thanks Willer Alves Uberlândia, MG, Brazil --------------------------------- Desafio AntiZona: participe do jogo de perguntas e respostas que vai dar 1 Renault Clio, computadores, câmeras digitais, videogames e muito mais! --0-1478827110-1062188375=:33322 Content-Type: text/html; charset=iso-8859-1 Content-Transfer-Encoding: 8bit
I'm getting in some troubles using stdScrollFunction. When I use it, it does the scrolling, but the screen is not actually updated in the new area. So, I'm getting a confused image when I do the scrolling.
 
What am I supposed to do?
 
Thanks
 
Willer Alves
Uberlândia, MG, Brazil



Desafio AntiZona: participe do jogo de perguntas e respostas que vai dar
1 Renault Clio, computadores, câmeras digitais, videogames e muito mais! --0-1478827110-1062188375=:33322-- From peter88@cs.kun.nl Mon, 01 Sep 2003 16:46:04 +0200 Date: Mon, 01 Sep 2003 16:46:04 +0200 From: Peter Achten peter88@cs.kun.nl Subject: [clean-list] stdScrollFunction --=====================_20296815==_.ALT Content-Type: text/plain; charset="iso-8859-1"; format=flowed Content-Transfer-Encoding: quoted-printable At 17:19 29-8-03 -0300, Alves da Silva Cruz Willer wrote: >I'm getting in some troubles using stdScrollFunction. When I use it, it=20 >does the scrolling, but the screen is not actually updated in the new=20 >area. So, I'm getting a confused image when I do the scrolling. > >What am I supposed to do? > >Thanks > >Willer Alves >Uberl=E2ndia, MG, Brazil Dear Willer Alves, In order to answer your question I need to know more in what situation you= =20 use this function. Can you tell me which Clean version you use, and what=20 Object I/O component? The stdScrollFunction is used to associate scrolling behaviour to a window= =20 or compound control. It only computes new origin points for the indicated=20 axis (horizontal/vertical). The actual update is done by means of the=20 WindowLook/ControlLook attribute. These are defined as: | ... | WindowLook Bool Look | ... for windows, and | ... | ControlLook Bool Look | ... for compound controls. The Bool argument should be True iff changing the=20 view frame of the window/compound control does not affect the content of=20 the complete document that is displayed by the window/compound control. In= =20 all other cases the Bool argument should be False. Regardless of the value of the Boolean, it is the responsibility of the=20 Look function to define proper content for the 'new' areas that are=20 collected in the updArea field of the UpdateState record that is passed to= =20 the Look function. Usually some code such as below is sufficient: look :: SelectState UpdateState *Picture -> *Picture look selectState updateState=3D:{updArea} picture # picture =3D foldr unfill picture updArea # ... your actual drawing code ... =3D picture Section 6.4.1. of the Tutorial to the CLEAN Object I/O Library explains=20 this in more detail. Hope this helps, Peter --=====================_20296815==_.ALT Content-Type: text/html; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable At 17:19 29-8-03 -0300, Alves da Silva Cruz Willer wrote:
I'm getting in some troubles using stdScrollFunction. When I use it, it does the scrolling, but the screen is not actually updated in the new area. So, I'm getting a confused image when I do the scrolling.
 
What am I supposed to do?
 
Thanks
 
Willer Alves
Uberl=E2ndia, MG, Brazil

Dear Willer Alves,

In order to answer your question I need to know more in what situation you use this function. Can you tell me which Clean version you use, and what Object I/O component?

The stdScrollFunction is used to associate scrolling behaviour to a window or compound control. It only computes new origin points for the indicated axis (horizontal/vertical). The actual update is done by means of the WindowLook/ControlLook attribute. These are defined as:

        | = ;      ...
        | = ;      WindowLook Bool Look
        | = ;      ...

for windows, and

        | = ;      ...
        | = ;      ControlLook Bool Look
        | = ;      ...

for compound controls. The Bool argument should be True iff changing the view frame of the window/compound control does not affect the content of the complete document that is displayed by the window/compound control. In all other cases the Bool argument should be False.

Regardless of the value of the Boolean, it is the responsibility of the Look function to define proper content for the 'new' areas that are collected in the updArea field of the UpdateState record that is passed to the Look function. Usually some code such as below is=20 sufficient:
look :: SelectState  UpdateState *Picture -> *Picture
look selectState updateState=3D:{updArea} picture
        # picture       =3D foldr unfill picture updArea
        # ... your actual drawing code ...
        =3D picture

Section 6.4.1. of the Tutorial to the CLEAN Object I/O Library explains this in more detail.

Hope this helps,
Peter
=00 --=====================_20296815==_.ALT-- From igouy@yahoo.com Thu, 11 Sep 2003 20:10:06 -0700 (PDT) Date: Thu, 11 Sep 2003 20:10:06 -0700 (PDT) From: isaac gouy igouy@yahoo.com Subject: [clean-list] unboxed spine strict lists and list comprehensions Is there a way to use unboxed spine strict lists in list comprehensions? module test import StdEnv, StdOverloadedList, StdStrictLists Start = Length b where a = [# x \\ x <- [1..5] !] b = [# x+1 \\ x <- a !] Type error [test.icl,6,comprehension]: cannot unify [Int] with [#v3!] best wishes, Isaac __________________________________ Do you Yahoo!? Yahoo! SiteBuilder - Free, easy-to-use web site design software http://sitebuilder.yahoo.com From johnvg@cs.kun.nl Fri, 12 Sep 2003 11:47:47 +0200 Date: Fri, 12 Sep 2003 11:47:47 +0200 From: John van Groningen johnvg@cs.kun.nl Subject: [clean-list] unboxed spine strict lists and list comprehensions Isaac Gouy wrote: >Is there a way to use unboxed spine strict lists in >list comprehensions? > >module test >import StdEnv, StdOverloadedList, StdStrictLists > >Start = Length b > where > a = [# x \\ x <- [1..5] !] > b = [# x+1 \\ x <- a !] > >Type error [test.icl,6,comprehension]: cannot unify >[Int] with [#v3!] Yes, use <|- (for an overloaded list) instead of <- (for a lazy list): b = [# x+1 \\ x <|- a !] Regards, John van Groningen From igouy@yahoo.com Fri, 12 Sep 2003 09:50:02 -0700 (PDT) Date: Fri, 12 Sep 2003 09:50:02 -0700 (PDT) From: isaac gouy igouy@yahoo.com Subject: [clean-list] unboxed spine strict lists and list comprehensions Thank you - predictably I found the information in the Clean Report within 5 minutes of posting the question ;-) Maybe I'll introduce a placebo and post questions to a silent oracle. I'm trying to examine where the lazy calls are using the time profiler, could you tell me how to interpret some of the function names given in the profiler, for example: c;46;23;11 best wishes, Isaac --- John van Groningen wrote: > Isaac Gouy wrote: > >Is there a way to use unboxed spine strict lists in > >list comprehensions? > Yes, use <|- (for an overloaded list) instead of <- > (for a lazy list): > > b = [# x+1 \\ x <|- a !] __________________________________ Do you Yahoo!? Yahoo! SiteBuilder - Free, easy-to-use web site design software http://sitebuilder.yahoo.com From daniel_yokomiso@yahoo.com.br Mon, 15 Sep 2003 21:54:10 -0300 Date: Mon, 15 Sep 2003 21:54:10 -0300 From: Daniel Yokomiso daniel_yokomiso@yahoo.com.br Subject: [clean-list] Exercise from Clean book Hi, I'm having some problem with exercise 2 from chapter two of Functional Programming in CLEAN (Draft - september 10, 2001). The question is: "Execute the start expression given in section 2.4.2. Rewrite the program such that it only prints the smallest number that is different from zero using the function until." where the expression from section 2.4.2 is: takeWhile ((<>) 0.0) (iterate (\x -> x/10.0) 1.0) So far so good, I come up with the following definitions: expected = last (takeWhile ((<>) 0.0) (iterate (\x -> x/10.0) 1.0)) smallest = until (\x -> tenth x == 0.0) tenth 1.0 tenth x = x/10.0 Start = expected == smallest After running it the system gives me "False". I checked the output of "smallest" and it's "0". Surprised I also checked it in Haskell (Hugs 98) and it's ok (expected == smallest). What's happening here? I'm using the Clean IDE v2.0 build 2001-12-18 Win (2.0) 2.0.1.42. Best regards, Daniel Yokomiso. "Being right too soon is socially unacceptable." - Robert A. Heinlein --- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.518 / Virus Database: 316 - Release Date: 11/9/2003 From ronny@cs.kun.nl Wed, 17 Sep 2003 13:58:22 +0200 Date: Wed, 17 Sep 2003 13:58:22 +0200 From: Ronny Wichers Schreur ronny@cs.kun.nl Subject: [clean-list] Exercise from Clean book Daniel Yokomiso writes (to the Clean discussion list): >[..] >expected = last (takeWhile ((<>) 0.0) (iterate (\x -> x/10.0) 1.0)) >smallest = until (\x -> tenth x == 0.0) tenth 1.0 >tenth x = x/10.0 > >Start = expected == smallest > > > After running it the system gives me "False". [..] > This is a rounding issue. See . Cheers, Ronny Wichers Schreur From ronny@cs.kun.nl Wed, 17 Sep 2003 14:09:49 +0200 Date: Wed, 17 Sep 2003 14:09:49 +0200 From: Ronny Wichers Schreur ronny@cs.kun.nl Subject: [clean-list] unboxed spine strict lists and list comprehensions isaac gouy writes (to the Clean discussion list): >I'm trying to examine where the lazy calls are using >the time profiler, could you tell me how to interpret >some of the function names given in the profiler, for >example: > >c;46;23;11 > This is the function that is generated for a comprehension on line 46, column 23. Here's a short list to unmangle the compiler generated function names: _c = case _g = guard _f = filter _if = if \ = lambda c = comprehension g = generator The function name is normally followed by ;l;c where l is the line number and c is the column number. Cheers, Ronny Wichers Schreur From daniel_yokomiso@yahoo.com.br Wed, 17 Sep 2003 21:14:56 -0300 Date: Wed, 17 Sep 2003 21:14:56 -0300 From: Daniel Yokomiso daniel_yokomiso@yahoo.com.br Subject: [clean-list] Exercise from Clean book Hi, Thanks. As I see the message is dated from july 2001. Will this be corrected? IMO if it isn't at least there should be a big warning in the Clean Book. It's a very strange bug, as simple changes in the code make it go away. The following works: smallest = until (hack is_zero tenth) tenth 1.0 where hack f g = (f o g) is_zero x = x == 0.0 but if we inline "hack" it stops working: smallest = until (is_zero o tenth) tenth 1.0 where is_zero x = x == 0.0 Best regards, Daniel Yokomiso. "Beauty is the first test: there is no permanent place in this world for ugly mathematics." - G. H. Hardy, A Mathematician's Apology ----- Original Message ----- From: "Ronny Wichers Schreur" To: Sent: Wednesday, September 17, 2003 8:58 AM Subject: Re: [clean-list] Exercise from Clean book > Daniel Yokomiso writes (to the Clean discussion list): > > >[..] > >expected = last (takeWhile ((<>) 0.0) (iterate (\x -> x/10.0) 1.0)) > >smallest = until (\x -> tenth x == 0.0) tenth 1.0 > >tenth x = x/10.0 > > > >Start = expected == smallest > > > > > > After running it the system gives me "False". [..] > > > This is a rounding issue. See > . > > > Cheers, > > Ronny Wichers Schreur --- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.518 / Virus Database: 316 - Release Date: 11/9/2003 From hugorufino@yahoo.com Wed, 1 Oct 2003 11:01:48 -0300 (ART) Date: Wed, 1 Oct 2003 11:01:48 -0300 (ART) From: =?iso-8859-1?q?Hugo=20Rufino?= hugorufino@yahoo.com Subject: [clean-list] htoclean examples --0-1890894225-1065016908=:16945 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit Hi, folks, i'm studing how to call C functions from Clean. I already know htoclean and i had some problems to understand how the example "example_array1" works. Being more specific why the index [-2] and [-1] in the following code? #define CleanIntArraySize(clean_int_array) (((unsigned int *)(clean_int_array))[-2]) #define CleanRealArraySize(clean_real_array) (((unsigned int *)(clean_real_array))[-2]) #define CleanCharArraySize(clean_char_array) (((unsigned int *)(clean_char_array))[-1]) There is a new version of htoclean? Anybody is studing how to call C function from Clean too? Thanks in advance, Hugo Leonardo --------------------------------- Yahoo! Mail - o melhor webmail do Brasil. Saiba mais! --0-1890894225-1065016908=:16945 Content-Type: text/html; charset=iso-8859-1 Content-Transfer-Encoding: 8bit
Hi, folks,
 
i'm studing how to call C functions from Clean. I already know htoclean and i had some problems to understand how the example "example_array1" works. Being more specific why the index [-2] and [-1] in the following code?
 
#define CleanIntArraySize(clean_int_array) (((unsigned int *)(clean_int_array))[-2])
#define CleanRealArraySize(clean_real_array) (((unsigned int *)(clean_real_array))[-2])
#define CleanCharArraySize(clean_char_array) (((unsigned int *)(clean_char_array))[-1])
There is a new version of htoclean?
Anybody is studing how to call C function from Clean too?
 
Thanks in advance,
 
Hugo Leonardo
 
 
 



Yahoo! Mail - o melhor webmail do Brasil. Saiba mais! --0-1890894225-1065016908=:16945-- From alanh@dcs.kcl.ac.uk Wed, 1 Oct 2003 22:49:47 +0100 Date: Wed, 1 Oct 2003 22:49:47 +0100 From: Alan Hutchinson alanh@dcs.kcl.ac.uk Subject: [clean-list] Synonym types The code I want to write will be much simpler if the types in it can be abbreviated as synonym types. The plan is to declare a function class with lots of instances, one for each type of control occurring in a graphical interface. The alternative would be to write long explicit types of ObjectIO Controls. The Clean compiler does not pass my code. The problem seems to lie in structures like the types in the following: module testSyn2 import StdEnv Start = testFn :: SynTypeA a b :== (a,b) :: Constr t1 t2 a b = C (t1 a b) (t2 a b) :: SynTypeB a b :== Constr SynTypeA SynTypeA a b testFn :: SynTypeA Int String testFn = (3,"It works.") This generates the error report Error [testSyn2.icl,11,SynTypeB]: SynTypeA used with wrong arity twice. If the type definition of SynTypeB is commented out then it compiles and runs as expected. Seeming reason: The parameters t1 and t2 in the definition of Constr have to be names of algebraic types, not synonym names. The Clean 2 Report says that each argument after "Constr" in the definition of SynTypeB can be a Type which may be a BrackType, which may be a TypeExpression, which can be a TypeConstructorName which can be the first symbol in any TypeLhs, such as the symbol SynTypeA in the above synonym type definition of SynTypeA. Have I got this right? is there a way round it? -- Alan Hutchinson Department of Computer Science King's College London Strand London WC2R 2LS alanh@dcs.kcl.ac.uk From arjenw@cs.kun.nl Thu, 02 Oct 2003 12:06:11 +0200 Date: Thu, 02 Oct 2003 12:06:11 +0200 From: Arjen van Weelden arjenw@cs.kun.nl Subject: [clean-list] Synonym types Hello, Alan Hutchinson wrote: > [snip] > The Clean compiler does not pass my code. The problem seems > to lie in structures like the types in the following: > > import StdEnv > > Start = testFn > > :: SynTypeA a b :== (a,b) > :: Constr t1 t2 a b = C (t1 a b) (t2 a b) > :: SynTypeB a b :== Constr SynTypeA SynTypeA a b > > testFn :: SynTypeA Int String > testFn > = (3,"It works.") > > [snip] > Seeming reason: > The parameters t1 and t2 in the definition of Constr > have to be names of algebraic types, not synonym names. > [snip] > Have I got this right? > is there a way round it? The Clean compiler does not support the use of synonym types with too many, or not enough, type arguments. It looks like this can be solved by changing the definition of SynTypeA to: :: SynTypeA :== (,) Unfortunately, the compiler does not support synonym types with kind other than *. You can define, but can never use, a synonym type for a 'real' type with not enough arguments (as I proposed for SynTypeA). You could replace SynTypeA with (,) everywhere in your code, but that is probably not what you want. regards, Arjen From arjenw@cs.kun.nl Thu, 02 Oct 2003 12:58:58 +0200 Date: Thu, 02 Oct 2003 12:58:58 +0200 From: Arjen van Weelden arjenw@cs.kun.nl Subject: [Fwd: Re: [clean-list] htoclean examples] Hi, In order to use HtoClean to use C code in Clean, you really don't need to know what the -2 and -1 are for, but here is my attempt to explain it. Clean stores (unboxed) arrays in memory something like the following C structs: struct RealArray { unsigned int size; unsigned int elementDescriptor; double[size] data }; struct IntArray { unsigned int size; unsigned int elementDescriptor; int[size] data }; struct CharArray { unsigned int size; char[size] data }; In the C code, you get a pointer to the data field of the struct. For Int and Real arrays, the size of the array is therefore stored in memory 2 integers before the address the pointer points to (1 for Char arrays or Strings). This explains the (unsigned int*), [-2], and [-1]. The elementDescriptor is not used in C, it is just the way the Clean stores arrays in memory. hope this removes some of the mystery, Arjen Hugo Rufino wrote: > Hi, folks, > > i'm studing how to call C functions from Clean. I already know htoclean > and i had some problems to understand how the example "example_array1" > works. Being more specific why the index [-2] and [-1] in the following > code? > > #define CleanIntArraySize(clean_int_array) (((unsigned int > *)(clean_int_array))[-2]) > #define CleanRealArraySize(clean_real_array) (((unsigned int > *)(clean_real_array))[-2]) > #define CleanCharArraySize(clean_char_array) (((unsigned int > *)(clean_char_array))[-1]) > There is a new version of htoclean? > Anybody is studing how to call C function from Clean too? > > Thanks in advance, > > Hugo Leonardo > > > > > > ------------------------------------------------------------------------ > *Yahoo! Mail * - > o melhor webmail do Brasil. Saiba mais! > From arjenw@cs.kun.nl Fri, 03 Oct 2003 10:48:51 +0200 Date: Fri, 03 Oct 2003 10:48:51 +0200 From: Arjen van Weelden arjenw@cs.kun.nl Subject: [clean-list] Synonym types Alan Hutchinson wrote: > Hello Arjen > Thanks for your mail. > It helps understand the matter, though I am still not sure > what to do about it. Hello Alan, If you want to use types in such a way, you will have to use algebraic or record types in Clean. Clean does not support something like Haskell's newtype. You could try using a algebraic type or a record type. The record type run-time representation is similar to tuples. :: SynTypeA a b = {fst :: a, snd :: b} :: Constr t1 t2 a b = C (t1 a b) (t2 a b) :: SynTypeB a b :== Constr SynTypeA SynTypeA a b testFn :: SynTypeA Int String testFn = {fst = 3, snd = "It works."} Start = (fst, snd) where {fst, snd} = testFn To simulate Haskell's newtype, because Clean does not (fully) support class instances for synonym types, you can also use a record with a single field. This is more efficient than an algebraic constructor. Unfortunately, it does require more syntax. regards, Arjen From tas@gmx.com Sat, 11 Oct 2003 06:04:47 +0200 Date: Sat, 11 Oct 2003 06:04:47 +0200 From: tas@gmx.com tas@gmx.com Subject: [clean-list] Questions about the IDE and AMD64 Hello, I´m a new user of Clean, and have got a couple of questions about the tools, on the Windows OS: 1 Is it possible to drive the Clean tools from the command line, rather than through the IDE? 2 Is there any plan to write a code generator for the AMD64 architecture? Any information would be appreciated. Regards Thomas From greenrd@greenrd.org Sat, 11 Oct 2003 18:36:39 +0100 Date: Sat, 11 Oct 2003 18:36:39 +0100 From: Robin Green greenrd@greenrd.org Subject: [clean-list] ADTs for fields in record types, please! One important thing that I find lacking in Clean 2.0, and which I hope will be addressed in a future release, is proper support for Abstract Data Types (ADTs) (aka interfaces in Java). It should be possible, in *any* context where a type needs to be specified, to specify by some means an Abstract Data Type, so that one or more functions is defined on this abstract type, but the actual implementation of the type (in terms of how it is represented and how the function(s) is/are implemented) can be freely varied on an instance-by-instance basis. "Freely" in the sense that the postcondition(s) of the function(s) should be adhered to, but the choice of representation should be entirely open. The best way to do that in Clean 2.0 seems to be to say something like myfunction::a -> Foo | ADT a But it is not possible to use the "| ADT a" syntax when defining the type of a field in a record type definition, for example. I have had to plump for a particular implementation of the ADT when declaring record types, which is an undesirable hack. It reduces the freedom to use more efficient implementations depending on the context. Will this be fixed in a future release? Or is there some alternative way of doing what I want to do that I've missed? -- Robin From m.wittebrood@mailbox.kun.nl Sun, 12 Oct 2003 17:43:06 +0200 Date: Sun, 12 Oct 2003 17:43:06 +0200 From: Marco Kesseler m.wittebrood@mailbox.kun.nl Subject: [clean-list] ADTs for fields in record types, please! >One important thing that I find lacking in Clean 2.0, and which >I hope will be addressed in a future release, is proper support >for Abstract Data Types (ADTs) (aka interfaces in Java). One of the things that I have been wondering about for some years, is why the "classes" as found in Clean actually aren't called "interfaces", as they lack an "object state". >It should be possible, in *any* context where a type needs to be >specified, to specify by some means an Abstract Data Type, so >that one or more functions is defined on this abstract type, >but the actual implementation of the type (in terms of how it >is represented and how the function(s) is/are implemented) >can be freely varied on an instance-by-instance basis. "Freely" >in the sense that the postcondition(s) of the function(s) >should be adhered to, but the choice of representation should >be entirely open. For me, the main question would be what to consider an "instance". In Clean, the class implementation must be specified for each type that is an instance of the class. And so, the implementation will vary on a type-by-type basis. For "objects" within that type, no variations are possible, if you look at classes alone. >The best way to do that in Clean 2.0 seems to be to say >something like > >myfunction::a -> Foo | ADT a > >But it is not possible to use the "| ADT a" syntax when >defining the type of a field in a record type definition, >for example. It has been a while since I played with that in Clean, so I am not entirely certain anymore what you CAN do syntactically in a record type definition. But see below. >I have had to plump for a particular implementation of the >ADT when declaring record types, which is an undesirable hack. >It reduces the freedom to use more efficient implementations >depending on the context. > >Will this be fixed in a future release? Or is there some >alternative way of doing what I want to do that I've missed? You might consider defining your own "classes", in the sense that you can create records that contain fields AND functions that act on that same object (including its fields). Effectively, you have then built your own function table. The "only" thing that Clean does not do for you, is pass the object implicitly as an argument to its functions, so you may will have to define functions for that. For example. // A class with one field, and two "methods" :: Integer = { value :: Int, inc :: Integer -> Integer, print :: Integer -> String } // Auxiliary functions (not needed in OO languages) inc :: Integer -> Integer inc i = i.inc i print :: Integer -> String print i = i.print i // Two Integer "constructors", with different implementations myInteger :: Int -> Integer myInteger i = {Integer | value = i, inc = \obj -> {obj & value = obj.value + 1}, print = \obj -> "myInteger: " +++ (toString obj.value) } yourInteger :: Int -> Integer yourInteger i = {Integer | value = i, inc = \obj -> {obj & value = obj.value + 2}, print = \obj -> "yourInteger: " +++ (toString obj.value) } // Let's run Start = print (inc (inc (myInteger 0))) This will print "myInteger: 2", but if you replace myInteger by yourInteger, the result will be "yourInteger: 4" It might have been nice to have some syntactic sugar for such "objects", especially to avoid the definitions of the inc and print functions. regards, Marco From fjh@cs.mu.OZ.AU Mon, 13 Oct 2003 13:39:29 +1000 Date: Mon, 13 Oct 2003 13:39:29 +1000 From: Fergus Henderson fjh@cs.mu.OZ.AU Subject: [clean-list] ADTs for fields in record types, please! On 11-Oct-2003, Robin Green wrote: > One important thing that I find lacking in Clean 2.0, and which > I hope will be addressed in a future release, is proper support > for Abstract Data Types (ADTs) (aka interfaces in Java). ... > It should be possible, in *any* context where a type needs to be > specified, to specify by some means an Abstract Data Type, so > that one or more functions is defined on this abstract type, > but the actual implementation of the type (in terms of how it > is represented and how the function(s) is/are implemented) > can be freely varied on an instance-by-instance basis. "Freely" > in the sense that the postcondition(s) of the function(s) > should be adhered to, but the choice of representation should > be entirely open. > > The best way to do that in Clean 2.0 seems to be to say > something like > > myfunction::a -> Foo | ADT a > > But it is not possible to use the "| ADT a" syntax when > defining the type of a field in a record type definition, > for example. ... > Will this be fixed in a future release? Or is there some > alternative way of doing what I want to do that I've missed? In Glasgow Haskell and Mercury, which both have quite similar type systems to Clean, the solution is to use existential types with type class constraints. In Glasgow Haskell, the syntax for existential types with type class constraints is like this: data MyType = forall a . ADT a => MyConstructor a In Mercury, it is :- type my_type ---> some [A] my_constructor(A) => adt(A). Clean does supports existential types, e.g. :: MyType = E.a: MyConstructor a and as you noted above, Clean supports type class constraints. But I don't know if Clean supports existential types with type class constraints, or what the syntax for them would be in Clean. The Clean 2.0 Report (draft) on the Clean web page doesn't specify any syntax for it, AFAICT, so perhaps it is not supported. -- Fergus Henderson | "I have always known that the pursuit The University of Melbourne | of excellence is a lethal habit" WWW: | -- the last words of T. S. Garp. From arjenw@cs.kun.nl Mon, 13 Oct 2003 10:48:10 +0200 Date: Mon, 13 Oct 2003 10:48:10 +0200 From: Arjen van Weelden arjenw@cs.kun.nl Subject: [clean-list] Questions about the IDE and AMD64 Hello Thomas, tas@gmx.com wrote: > Hello, > > I´m a new user of Clean, and have got a couple of questions about the > tools, on the Windows OS: > > 1 Is it possible to drive the Clean tools from the command line, rather > than through the IDE? it is in the archive: http://www.cs.kun.nl/pipermail/clean-list/2003/002380.html > > 2 Is there any plan to write a code generator for the AMD64 architecture? I don't know, sorry. > > Any information would be appreciated. > > Regards > Thomas > regards, Arjen From m.wittebrood@mailbox.kun.nl Mon, 13 Oct 2003 15:54:19 +0200 Date: Mon, 13 Oct 2003 15:54:19 +0200 From: Marco Kesseler m.wittebrood@mailbox.kun.nl Subject: [clean-list] ADTs for fields in record types, please! In addition to Fergus' answer: >In Mercury, it is > > :- type my_type ---> some [A] my_constructor(A) => adt(A). > >Clean does supports existential types, e.g. > > :: MyType = E.a: MyConstructor a > >and as you noted above, Clean supports type class constraints. >But I don't know if Clean supports existential types with type class >constraints, or what the syntax for them would be in Clean. >The Clean 2.0 Report (draft) on the Clean web page doesn't specify >any syntax for it, AFAICT, so perhaps it is not supported. I am not sure about support in Clean for existential types with type class constraints either. In principle, this would seem the best solution, although this depends on the kind of flexibility people want with respect to dynamically defining and changing behaviours. With respect to my earlier example, I wish that I could just have changed the "Integer" typedef in the following way in order to avoid hard-coding the integer (this was actually what I had in mind when coming up with the example). :: Integer = E.i { value :: i, inc :: Integer -> Integer, print :: Integer -> String } The problem with this is, that the compiler starts to complain about the original "constructors" (see my previous message). As often, the compiler is right: it cannot conclude that the methods we are specifying in the constructor act on the same type as the value. The only way to avoid this, is to define functions on the internal representation directly, as follows (this works, but it comes at a cost, see below). :: Integer = E.i: { value :: i, inc :: i -> i, print :: i -> String } inc :: Integer -> Integer inc obj=:{inc, value} = {obj & value = inc value} // The 1.3 compiler cannot cope with the following. Don't know why, and I don't know about 2.0 //inc obj = {obj & value = obj.inc obj.value} print :: Integer -> String print {print, value} = print value myInteger :: Int -> Integer myInteger i = {Integer | value = i, inc = (+) 1, print = \i -> "myInteger: " +++ (toString i) } // etc.... I do find the "constructors" more clear in this situation, but the "problem" I have with this, is that the "methods" have to be very specific in their public signature about what parts of the object they refer to. In the end, this affects maintainability of the code, as you have to change the method signatures as soon as they start taking different object fields as arguments, which should be irrelevant for the "external" interface. This problem also exists in solutions that employ type class constraints: the contraints provide an interface on an _element_ of the object, not on the object _itself_ (or is there a way?). There are two alternatives, but both are not quite "right": - parametrise the Integer type with its internal representation. This works too, but exposes part of the object internals (not a pretty sight). - one might resort to using Dynamics. I am not too fond about that either - if only for the runtime testing -, but neither am I experienced in using them (I am still on 1.3). Perhaps it would be nice to have an extension that would allow writing the following code (haven't really thought this over though, so shoot me if there's some bloody issue, figuratively that is). class Integer = E.i { value :: i, inc :: -> Integer // All methods implicitly have the object itself as first argument print :: -> String } Integer :: Int -> Integer // A constructor Integer i = { value = i, inc = value -> value + 1 // i.e. implicitly generate method code like in the original code print = toString value } And then the compiler should: - implicitly generate "method" calls for these objects - avoid the type-system complaining about not being able to determine the type of the existential value, as all methods are known to always operate on their own object. So in the end you can either call: print (inc (inc (Integer 0)) or: (Integer 0).inc.inc.print // i.e. selection, not function composition or (not all that different): print (with (Integer 0) do {inc; inc;}) Hmmm, is there a relation with Monads, but then in a way that people with an OO background can understand? Maybe this is nice for passing around unique states as well? (Don't know, I am no longer an active researcher). :-) regards, Marco From m.wittebrood@mailbox.kun.nl Mon, 13 Oct 2003 17:01:48 +0200 Date: Mon, 13 Oct 2003 17:01:48 +0200 From: Marco Kesseler m.wittebrood@mailbox.kun.nl Subject: [clean-list] ADTs for fields in record types, please! Turns out one thing was wrong in my previous message (so now, I am talking to myself): >This problem also exists in >solutions that employ type class constraints: the contraints provide >an interface on an _element_ of the object, not on the object >_itself_ (or is there a way?). This is not true. The element IS the object in that case. but the rest still doesn't sound completely off. regards, Marco From fjh@cs.mu.OZ.AU Tue, 14 Oct 2003 01:33:58 +1000 Date: Tue, 14 Oct 2003 01:33:58 +1000 From: Fergus Henderson fjh@cs.mu.OZ.AU Subject: [clean-list] ADTs for fields in record types, please! On 13-Oct-2003, Marco Kesseler wrote: > :: Integer = E.i: { > value :: i, > inc :: i -> i, > print :: i -> String > } If Clean doesn't support existential types with type class constraints, I suppose you could still combine the two using existential types like the one above, if you don't mind a bit of additional boilerplate code. That is, if you have a type class with say two methods, class Integer i { inc :: i -> i, print :: i -> String } then you can define a corresponding (unconstrained) existential type with a field for the value and an explicit higher-order function field for each method: :: AnyInteger = E.i: { value :: i, inc_meth :: i -> i, print_meth :: i -> String } You can then provide a conversion function to convert from any instance of the type class to the existential type: mkAnyInteger :: i -> AnyInteger | Integer i mkAnyInteger i = { value = i & inc_meth = inc & print_meth = print } You can also make the existential type an instance of the type class, so that you never need to do any explicit conversions in the other direction: instance Integer AnyInteger where { inc any=:{ value, inc_meth } = { any & value = inc_meth value } print any=:{ value, print_meth } = print_meth value } (I hope I got all the syntax roughly right; this is just off the top of my head, and I don't have a Clean implementation around to test it.) > I do find the "constructors" more clear in this situation, but the > "problem" I have with this, is that the "methods" have to be very > specific in their public signature about what parts of the object > they refer to. In the end, this affects maintainability of the code, > as you have to change the method signatures as soon as they start > taking different object fields as arguments, which should be > irrelevant for the "external" interface. This problem also exists in > solutions that employ type class constraints: the contraints provide > an interface on an _element_ of the object, not on the object > _itself_ (or is there a way?). I didn't really understand what you were getting at there. Perhaps an example might help to clarify your point. -- Fergus Henderson | "I have always known that the pursuit The University of Melbourne | of excellence is a lethal habit" WWW: | -- the last words of T. S. Garp. From m.wittebrood@mailbox.kun.nl Tue, 14 Oct 2003 00:10:10 +0200 Date: Tue, 14 Oct 2003 00:10:10 +0200 From: Marco Kesseler m.wittebrood@mailbox.kun.nl Subject: [clean-list] ADTs for fields in record types, please! >> I do find the "constructors" more clear in this situation, but the >> "problem" I have with this, is that the "methods" have to be very >> specific in their public signature about what parts of the object >> they refer to. In the end, this affects maintainability of the code, >> as you have to change the method signatures as soon as they start >> taking different object fields as arguments, which should be >> irrelevant for the "external" interface. This problem also exists in >> solutions that employ type class constraints: the contraints provide >> an interface on an _element_ of the object, not on the object >> _itself_ (or is there a way?). > >I didn't really understand what you were getting at there. >Perhaps an example might help to clarify your point. The main problem is that the "Integer" object below exposes too much of its internal types. There should be no reason to tell the outside world that inc works on the "i" field like this. :: Integer = E.i: { value :: i, inc :: i -> i, print :: i -> String } So we end up having to define "wrapper" functions to hide this flaw (like the ones you suggested), and this introduces extra work. Things would be simpler with objects like the following, as they would allow one to specify that they operate on the object they are contained in, without reveiling on what fields exactly. Dealing with these fields would then become purely a matter of the method itself, not of some external wrapper function. :: Integer = E.i { value :: i, inc :: Integer -> Integer, print :: Integer -> String } If this were possible, it would make wrapper functions far less mandatory, and at least a lot simpler. It is also one step closer to a public interface that does not mention the value field at all, in the same way that abstract types do not mention their implementation. I think these "little" issues matter a lot for useablility. regards, Marco From fjh@cs.mu.OZ.AU Tue, 14 Oct 2003 12:56:37 +1000 Date: Tue, 14 Oct 2003 12:56:37 +1000 From: Fergus Henderson fjh@cs.mu.OZ.AU Subject: [clean-list] ADTs for fields in record types, please! On 14-Oct-2003, Marco Kesseler wrote: > >> I do find the "constructors" more clear in this situation, but the > >> "problem" I have with this, is that the "methods" have to be very > >> specific in their public signature about what parts of the object > >> they refer to. In the end, this affects maintainability of the code, > >> as you have to change the method signatures as soon as they start > >> taking different object fields as arguments, which should be > >> irrelevant for the "external" interface. This problem also exists in > >> solutions that employ type class constraints: the contraints provide > >> an interface on an _element_ of the object, not on the object > >> _itself_ (or is there a way?). > > > >I didn't really understand what you were getting at there. > >Perhaps an example might help to clarify your point. > > The main problem is that the "Integer" object below exposes too much > of its internal types. There should be no reason to tell the outside > world that inc works on the "i" field like this. > > :: Integer = E.i: { > value :: i, > inc :: i -> i, > print :: i -> String > } But "i" here is completely abstract. There's really no exposing of internal implementation details of `i' going on here. > So we end up having to define "wrapper" functions to hide this flaw > (like the ones you suggested), and this introduces extra work. The wrappers are indeed a little bit of extra work. So it would be nice to be able to use a type-class constrained existential type, like you can do in Glasgow Haskell and Mercury, e.g. something like (inventing new Clean syntax, and overloading the name "Integer" as both a type class and a type): :: Integer = E.i | Integer i: { value :: i } It would even be nice to have such a type generated automatically from the class declaration, and to have the instance generation that makes the type be an instance of the class be similarly generated automatically. (Of course this only works in a restricted set of cases, not for all type classes, e.g. it only makes sense for single-parameter type classes, not multi-parameter type classes.) > Things > would be simpler with objects like the following, as they would allow > one to specify that they operate on the object they are contained in, > without reveiling on what fields exactly. Dealing with these fields > would then become purely a matter of the method itself, not of some > external wrapper function. > > :: Integer = E.i { > value :: i, > inc :: Integer -> Integer, > print :: Integer -> String > } Now here I disagree. Using an approach like that isn't simpler at all, IMHO. Firstly, like the original work-around, but unlike the solution using typeclass-constrained existential types, you've duplicated the "inc" and "print" members from the class in the data type. Secondly, it is fundamentally not type safe, because it allows you to apply methods from one type of Integer to a different type of Integer. -- Fergus Henderson | "I have always known that the pursuit The University of Melbourne | of excellence is a lethal habit" WWW: | -- the last words of T. S. Garp. From divip@aszt.inf.elte.hu Tue, 14 Oct 2003 14:32:58 +0200 (CEST) Date: Tue, 14 Oct 2003 14:32:58 +0200 (CEST) From: Divianszky Peter divip@aszt.inf.elte.hu Subject: [clean-list] How to compile Sparkle / How to compile big projects? Hi, I would like to compile the sparkle source from the Clean homepage but it seems too big to link (I think the linker is which aborts with 'Heap full' during the compilation). What is the easiest way to compile Sparkle? Thanks, Peter Divianszky From xset@mail.ru Tue, 14 Oct 2003 21:02:01 +0700 Date: Tue, 14 Oct 2003 21:02:01 +0700 From: XSet xset@mail.ru Subject: [clean-list] Questions about Clean applications and tutorials This is a multi-part message in MIME format. ------=_NextPart_000_0009_01C39296.6A1F6D20 Content-Type: text/plain; charset="koi8-r" Content-Transfer-Encoding: quoted-printable Hello, I am newbee to Clean and follow Clean versions during two past years.=20 I see Clean is powerful language, but I wonder Where are many real world = applications written with it ? It will be great to see sources of such application (I = guess Clean sources is helpful, but can I understand how it works?). I searched for tutorials and found = only few introductional ones. Unfortunately, Clean additional libraries = like Functional Fragments aren't updated and have not quite enough = explanations. it will be very good to include something like working = jpeg decoder to examples.=20 IMHO such things are central factors of language usability and = popularity. I wish Clean to become everyday language for my needs. Any links on apps or tutorials will be highly appreciated. Best regards XSet ------=_NextPart_000_0009_01C39296.6A1F6D20 Content-Type: text/html; charset="koi8-r" Content-Transfer-Encoding: quoted-printable
Hello,
 
I am newbee to Clean and follow=20 Clean versions during two past years.
I see Clean is powerful language, = but I=20 wonder Where are many real world applications
written with it ? It will be = great to see=20 sources of such application (I guess Clean sources is = helpful,
but can I understand how it = works?). I=20 searched for tutorials and found only few introductional ones. = Unfortunately,=20 Clean additional libraries like Functional Fragments aren't updated and = have not=20 quite enough explanations. it will be very good to include something = like=20 working jpeg decoder to examples.
 
IMHO such things are central = factors of=20 language usability and popularity. I wish Clean to become everyday = language for=20 my needs.
 
Any links on apps or tutorials = will be highly=20 appreciated.
 
Best regards
XSet
------=_NextPart_000_0009_01C39296.6A1F6D20-- From johnvg@cs.kun.nl Tue, 14 Oct 2003 17:42:28 +0200 Date: Tue, 14 Oct 2003 17:42:28 +0200 From: John van Groningen johnvg@cs.kun.nl Subject: [clean-list] How to compile Sparkle / How to compile big projects? Peter Divianszky wrote: >I would like to compile the sparkle source from the >Clean homepage but it seems too big to link (I think the linker is >which aborts with 'Heap full' during the compilation). >What is the easiest way to compile Sparkle? You can increase the size of the heap of the linker to 32 mb by adding: : -h 32m after the file name of the static linker in the environment dialog of the IDE. You can also increase the heap size of the compiler, by adding : -h 32m after the file name of the compiler. It usually compiles sparkle faster with a larger heap. Regards, John van Groningen From m.wittebrood@mailbox.kun.nl Wed, 15 Oct 2003 00:32:37 +0200 Date: Wed, 15 Oct 2003 00:32:37 +0200 From: Marco Kesseler m.wittebrood@mailbox.kun.nl Subject: [clean-list] ADTs for fields in record types, please! On Tue, 2003-10-14 at 04:56, Fergus Henderson wrote: > On 14-Oct-2003, Marco Kesseler wrote: > > > > The main problem is that the "Integer" object below exposes too much > > of its internal types. There should be no reason to tell the outside > > world that inc works on the "i" field like this. > > > > :: Integer = E.i: { > > value :: i, > > inc :: i -> i, > > print :: i -> String > > } > > But "i" here is completely abstract. There's really no exposing of > internal implementation details of `i' going on here. Yes, but I was not talking about the internals of 'i'. I was talking about the internals of 'Integer'. If you add some additional field to the Integer object, one would have to "expose" the (possibly concrete) type of this field as well in the methods that use it. And one would have to adapt the wrapper functions. :: Integer = E.i { value :: i, numberOfIncCalls :: Int, inc :: Int i -> (Int, i) print :: i -> String } Now you could argue that the complete state of each object should be existential, and that any new fields should be added IN this type (i.e. within the definition of i). If that is what you are proposing, you may be right: little seems lost if people know that the methods act on this type. And indeed: this would really hide ALL fields. But then suppose that the "print" function suddenly needs to call "inc" internally. Must we then change the type of the print function into: print :: (i -> i) i -> string, and adapt the wrapper functions as well? Note that we cannot move the inc function into the existential "i", as then it becomes inaccessible for everybody except "print". > > So we end up having to define "wrapper" functions to hide this flaw > > (like the ones you suggested), and this introduces extra work. > > The wrappers are indeed a little bit of extra work. So it would > be nice to be able to use a type-class constrained existential type, > like you can do in Glasgow Haskell and Mercury, e.g. something like > (inventing new Clean syntax, and overloading the name "Integer" as > both a type class and a type): > > :: Integer = E.i | Integer i: { value :: i } I agree that this kind of functionality is needed. On the other hand, for "object"-related stuff I would very much like a notation that more closely matches object oriented languages (i.e. define the data and its methods in one construct). > It would even be nice to have such a type generated automatically from > the class declaration, and to have the instance generation that makes > the type be an instance of the class be similarly generated automatically. > (Of course this only works in a restricted set of cases, not for all > type classes, e.g. it only makes sense for single-parameter type > classes, not multi-parameter type classes.) I don't quite follow this. If an object has more than one existential type, how do you then define an interface for it using a type-class constraint? > > Things > > would be simpler with objects like the following, as they would allow > > one to specify that they operate on the object they are contained in, > > without reveiling on what fields exactly. Dealing with these fields > > would then become purely a matter of the method itself, not of some > > external wrapper function. > > > > :: Integer = E.i { > > value :: i, > > inc :: Integer -> Integer, > > print :: Integer -> String > > } > > Now here I disagree. Using an approach like that isn't simpler at all, IMHO. > Firstly, like the original work-around, but unlike the solution using > typeclass-constrained existential types, you've duplicated the "inc" > and "print" members from the class in the data type. Ehm, I suspect that I didn't express myself clearly enough. The (invented!) notation above would actually BE the class definition. I should have made clear that I was not talking about any real Clean syntax here (the compiler won't accept the construct above). > Secondly, it is fundamentally not type safe, because it allows you to > apply methods from one type of Integer to a different type of Integer. Only IF the compiler would allow you to apply one of the methods to something else than their own object. I would propose that it would not. More precisely, I would propose that the compiler always apply these methods to their own object implicitly, just like many OO implementations do. regards, Marco From fjh@cs.mu.OZ.AU Wed, 15 Oct 2003 12:15:15 +1000 Date: Wed, 15 Oct 2003 12:15:15 +1000 From: Fergus Henderson fjh@cs.mu.OZ.AU Subject: [clean-list] ADTs for fields in record types, please! On 15-Oct-2003, Marco Kesseler wrote: > On Tue, 2003-10-14 at 04:56, Fergus Henderson wrote: > > On 14-Oct-2003, Marco Kesseler wrote: > > > > > > The main problem is that the "Integer" object below exposes too much > > > of its internal types. There should be no reason to tell the outside > > > world that inc works on the "i" field like this. > > > > > > :: Integer = E.i: { > > > value :: i, > > > inc :: i -> i, > > > print :: i -> String > > > } > > > > But "i" here is completely abstract. There's really no exposing of > > internal implementation details of `i' going on here. > > Yes, but I was not talking about the internals of 'i'. I was talking > about the internals of 'Integer'. If you add some additional field to > the Integer object, one would have to "expose" the (possibly concrete) > type of this field as well in the methods that use it. And one would > have to adapt the wrapper functions. But, other than adding additional higher-order function terms corresponding to additional methods, you *won't* change the Integer object. > :: Integer = E.i { > value :: i, > numberOfIncCalls :: Int, > inc :: Int i -> (Int, i) > print :: i -> String > } > > Now you could argue that the complete state of each object should be > existential, and that any new fields should be added IN this type (i.e. > within the definition of i). Exactly! > If that is what you are proposing, you may > be right: little seems lost if people know that the methods act on this > type. And indeed: this would really hide ALL fields. Right. > But then suppose that the "print" function suddenly needs to call "inc" > internally. Must we then change the type of the print function No... why would you need to do that? print just calls inc. > > It would even be nice to have such a type generated automatically from > > the class declaration, and to have the instance generation that makes > > the type be an instance of the class be similarly generated automatically. > > (Of course this only works in a restricted set of cases, not for all > > type classes, e.g. it only makes sense for single-parameter type > > classes, not multi-parameter type classes.) > > I don't quite follow this. I'm just saying that if you have a type class declaration such as -- Haskell syntax typeclass Foo a where foo a -> Int bar a -> a -> a ... then it would be nice if the compiler would automatically generate a corresponding existential type AnyFoo -- (Glasgow) Haskell syntax data AnyFoo = forall a . Foo a => MkAnyFoo a and a corresponding instance declaration -- Haskell syntax instance Foo AnyFoo where foo (MkAnyFoo f) = foo f bar (MkAnyFoo x) (MkAnyFoo y) = bar x y ... Though probably this would work best if it didn't actually add the "Any" and "MkAny" prefixes that I used above, and instead just overloaded the name "Foo" as three things: a type class name, a type name, and a data constructor name. My parenthetical remark above was just saying that if you have a type class declaration for a multi-parameter type class, e.g. typeclass Quux a b where ... then you don't want the compiler to automatically generate a corresponding existential type and instance declaration, since they wouldn't make sense. > If an object has more than one existential > type, how do you then define an interface for it using a type-class > constraint? I'm not sure what you mean by "more than one existential type". If you are talking about an object that can satisfy more than one interface, then you can define a type class for each interface. > > > Things > > > would be simpler with objects like the following, as they would allow > > > one to specify that they operate on the object they are contained in, > > > without reveiling on what fields exactly. Dealing with these fields > > > would then become purely a matter of the method itself, not of some > > > external wrapper function. > > > > > > :: Integer = E.i { > > > value :: i, > > > inc :: Integer -> Integer, > > > print :: Integer -> String > > > } > > > > Now here I disagree. Using an approach like that isn't simpler at all, IMHO. > > Firstly, like the original work-around, but unlike the solution using > > typeclass-constrained existential types, you've duplicated the "inc" > > and "print" members from the class in the data type. > > Ehm, I suspect that I didn't express myself clearly enough. The > (invented!) notation above would actually BE the class definition. I > should have made clear that I was not talking about any real Clean > syntax here (the compiler won't accept the construct above). The code above looks like valid Clean syntax to me, with an already-defined meaning. Oh, apart from the fact that it is missing a ":" after the "E.i" -- is that what you meant? I thought that was just a typo. If you are proposing that the presence or absence of a ":" here have some semantic meaning, then I think that is a rather confusing and error-prone choice of syntax. If you are proposing a new meaning for what is already valid Clean syntax, then that is definitely confusing and IMHO is not a good idea. -- Fergus Henderson | "I have always known that the pursuit The University of Melbourne | of excellence is a lethal habit" WWW: | -- the last words of T. S. Garp. From m.wittebrood@mailbox.kun.nl Thu, 16 Oct 2003 00:24:25 +0200 Date: Thu, 16 Oct 2003 00:24:25 +0200 From: Marco Kesseler m.wittebrood@mailbox.kun.nl Subject: [clean-list] ADTs for fields in record types, please! On Wed, 2003-10-15 at 04:15, Fergus Henderson wrote: > On 15-Oct-2003, Marco Kesseler wrote: > > > > Yes, but I was not talking about the internals of 'i'. I was talking > > about the internals of 'Integer'. If you add some additional field to > > the Integer object, one would have to "expose" the (possibly concrete) > > type of this field as well in the methods that use it. And one would > > have to adapt the wrapper functions. > > But, other than adding additional higher-order function terms corresponding > to additional methods, you *won't* change the Integer object. I was rather thinking about changing existing type signatures corresponding to existing methods that need to be changed because at some point in time they happen to need access to some additional field. But yes, this holds for new methods too. There may be many of them, and it should not be necessary. > > If that is what you are proposing, you may > > be right: little seems lost if people know that the methods act on this > > type. And indeed: this would really hide ALL fields. > > Right. > > > But then suppose that the "print" function suddenly needs to call "inc" > > internally. Must we then change the type of the print function > > No... why would you need to do that? > > print just calls inc. Well, IF inc is known at compile-time, then yes. But inc is just a field in this particular object. It can be replaced by another value, even if it acts on an existential value: there may be a method in the object that arranges this. I think that there can be good reasons to change the behaviour of some existing object at runtime. Building a new object may not be an option, because you may not be able to access the internals of the existing one. But also because functions are values, so there should be no fundamental difference between fields and methods. > > > My parenthetical remark above was just saying that if you have a type > class declaration for a multi-parameter type class, e.g. > > typeclass Quux a b where > ... > > then you don't want the compiler to automatically generate a > corresponding existential type and instance declaration, since > they wouldn't make sense. > > > If an object has more than one existential > > type, how do you then define an interface for it using a type-class > > constraint? > > I'm not sure what you mean by "more than one existential type". [note that the following is NOT Clean syntax. More info can be found entirely below.] class Window c = E.m b g t e: { content :: c, menus :: m, // some menu definition buttons :: b, // some definition of buttons theme :: t, // some window theme gizmos :: g, // some set of gizmo's environment :: e, // some relation to some environment position :: Pos, size :: Size, move :: Pos -> Window, resize :: Size -> Window, addContent :: c -> Window } I may prefer the above over [This IS Clean syntax]: :: Window c = E.s: { windowState :: s, move :: s Pos -> s, resize :: s Size -> s, addContent :: s c -> s } because in the latter case, I have to look somewhere else to see what a window is about. Or for whatever reason. I think that it is quite natural to have multiple existential types in some object class. Note that I am NOT really considering the use of existential types for data hiding. Most of all, I find them useful for defining extensible types. I think that data hiding deserves its own constructs, such as just exposing the "public" stuff in the Clean dcl files. > If you are talking about an object that can satisfy more than one interface, > then you can define a type class for each interface. No, I did not have that in mind. See above. Yes, one should be able make any of the the Windows classes above an instance of various type classes and thus give it various interfaces. I also think that one should be able to place type-class constraints on one or more of their existential fields. This would allow one to select one of these existential fields and actually do something with it (i.e. without having to define additional functions). (and that is also potentially a reason to have multiple existential types in the object). > > Ehm, I suspect that I didn't express myself clearly enough. The > > (invented!) notation above would actually BE the class definition. I > > should have made clear that I was not talking about any real Clean > > syntax here (the compiler won't accept the construct above). > > The code above looks like valid Clean syntax to me, with an already-defined > meaning. Oh, apart from the fact that it is missing a ":" after the "E.i" -- > is that what you meant? I thought that was just a typo. > > If you are proposing that the presence or absence of a ":" here have some > semantic meaning, then I think that is a rather confusing and error-prone > choice of syntax. > > If you are proposing a new meaning for what is already valid Clean syntax, > then that is definitely confusing and IMHO is not a good idea. Like I said, this was not intended as real syntax at all, and I should have made this clear. Now what I would LIKE is: * use the term "interface" for what is currrently known as classes in Clean. Simply because Clean (or Haskell) classes do _not_ capture the notion of an object state. They just define interfaces for types. * Repurpose the term "class" for the kind of objects I was talking about above, and get rid of explicit references to the object itself in method definitions. So: // This is NO Clean syntax at all... class Integer = E.i: { value :: i, inc :: -> Integer, print :: -> String } regards, Marco From gemi@bluewin.ch Thu, 30 Oct 2003 00:54:42 +0100 Date: Thu, 30 Oct 2003 00:54:42 +0100 From: Gerard Milmeister gemi@bluewin.ch Subject: [clean-list] Packaging as RPM Hi, I would like to package clean as an RPM. What is the procedure to build a complete distribution from source? Regards -- Gérard Milmeister Tannenrauchstrasse 35 8038 Zürich gemi@bluewin.ch From clean@cs.kun.nl Fri, 31 Oct 2003 12:02:28 +0100 Date: Fri, 31 Oct 2003 12:02:28 +0100 From: Clean Support clean@cs.kun.nl Subject: [clean-list] Clean 2.1.0 available for Windows, Mac, Linux and Solaris Clean 2.1.0 is now available for Windows, Mac OS X, Linux (Intel) and Solaris (Sparc) at . New in 2.1.0 (compared to version 2.0.2): – Abstract synonym types. Example (in a dcl module): :: Abs (:== Int) means that Abs is abstract during type checking, but its implementation can be used by the compiler to generate more efficient code. – Boxed records. Example: the exclamation mark in :: R = !{f1 :: Int, f2 :: Int} indicates that values of type R should always stay boxed, in particular when passed as a strict argument to a function or returned as a strict value from a function. – Mac OS X support including Object I/O 1.2 (Carbon) The Clean System runs only under Mac OS X. It features the same IDE as the Windows version and can produce executables for Carbon PEF (the default), Carbon MachO (using the linker from the Apple developer tools) and Mac OS 9. The Object I/O library is currently available for Carbon only. – Stack overflow checks without overhead and always enabled. Stack overflows are detected using a guard page. The stack check option in the Project > Diagnostics panel refers to the old method with overhead and should be disabled. – Optimising linkers for Linux and Solaris. - Direct code generation (instead of using an assembler) on Solaris. - htoclean replaces fclc (Linux and Solaris). - Version for Linux that bootstraps the compiler from intermediate ABC files. - New optimisations * tail recursion modulo cons optimisation. * faster code for division and remainder by integer constants (IA32 and PowerPC); * faster code for multiplications with certain integer constants; * faster real to string conversion (Windows); - Improvements to the IDE * syntax colouring of type definitions and function types; * standard keyboard mapping for Windows; * alt-key works as expected on Windows. - Option "write stderr to file" on Mac OS X (Carbon) behaves the same as on Windows: it only writes to file and doesn't copy the error messages to a console window. – Major improvements in the implementation of dynamics (Windows only). Generics and dynamics are now standard in Clean 2.1. - Numerous bug fixes. The documentation (most notably the Clean Language report) is not up-to-date. We will fix this in a next minor release. The source code of the complete Clean System is also available from the download page. This includes the sources for the Clean Compiler, Code Generator, IDEs, Profilers, Dynamics support, Linkers, Run-Time System and the Sparkle theorem prover. Clean Support http://www.cs.kun.nl/~clean/ From jeremy.shaw@lindows.com Sun, 02 Nov 2003 13:51:59 -0800 Date: Sun, 02 Nov 2003 13:51:59 -0800 From: Jeremy Shaw jeremy.shaw@lindows.com Subject: [clean-list] Question about uniqueness type error Hello, I am getting a uniqueness error I can not explain when I try to combine type synonyms and classes. I can't figure out if I am misunderstanding something, or if it is a compiler bug. The following code is based on some actually code I wrote, but with all the irrelevant stuff stripped out for readability. -----> module test import StdEnv :: MonoFrames a :== .{#a} :: StereoFrames a :== .(.{#a},.{#a}) :: Stream a = MonoStream .(MonoFrames a) | StereoStream .(StereoFrames a) class Frames a where mixInFrames :: *a *a -> *a instance Frames (MonoFrames *Int) where mixInFrames :: *(MonoFrames *Int) *(MonoFrames *Int) -> *(MonoFrames *Int) mixInFrames frames1 frames2 = frames2 // This variation does not work instance Frames (StereoFrames *Int) where mixInFrames :: *(StereoFrames *Int) *(StereoFrames *Int) -> *(StereoFrames *Int) mixInFrames (f1l, f1r) (f2l, f2r) = (f2l, f2r) /* // This one works instance Frames (*{#*Int},*{#*Int}) where mixInFrames :: *(*{#*Int},*{#*Int}) *(*{#*Int},*{#*Int}) -> *(*{#*Int},*{#*Int}) mixInFrames (f1l, f1r) (f2l, f2r) = (f2l, f2r) */ // so does this mixInFrames2 :: *(StereoFrames *Int) *(StereoFrames *Int) -> *(StereoFrames *Int) mixInFrames2 (f1l, f1r) (f2l, f2r) = (f2l, f2r) mixInStream :: *(Stream *Int) *(Stream *Int) -> *(Stream *Int) mixInStream (MonoStream frames1) (MonoStream frames2) = (MonoStream (mixInFrames frames1 frames2)) mixInStream (StereoStream frames1) (StereoStream frames2) = (StereoStream (mixInFrames frames1 frames2)) Start = "Hello, World!" <----- If I try to compile the code as shown, I get the following error: clm test -o test Compiling test Uniqueness error [test.icl,36,mixInStream]:"argument 1 of StereoStream" attribute at indicated position could not be coerced *(^ {#*Int},{#*Int}) Uniqueness error [test.icl,36,mixInStream]:"argument 2 of mixInFrames" attribute at indicated position could not be coerced *(StereoFrames ^ *Int) Uniqueness error [test.icl,36,mixInStream]:"argument 1 of mixInFrames" attribute at indicated position could not be coerced *(StereoFrames ^ *Int) make: *** [test] Error 1 If I comment out this instance: instance Frames (StereoFrames *Int) And uncomment this instance: instance Frames (*{#*Int},*{#*Int}) The code compiles without any errors. OR, if I change mixInStream to call mixInFrames2, it also compiles fine. So I am confused. How come mixInFrames2 works, but the 'instance Frames (StereoFrames *Int)' gives a uniqueness error. Am I correct in thinking that: mixInFrames :: *(StereoFrames *Int) *(StereoFrames *Int) -> *(StereoFrames *Int) is a type synonym for: mixInFrames :: *(*{#*Int},*{#*Int}) *(*{#*Int},*{#*Int}) -> *(*{#*Int},*{#*Int}) Thanks. Jeremy Shaw. ps. I tested this with clean 2.1 for linux. From dvanarkel@mac.com Sun, 2 Nov 2003 23:35:34 +0100 Date: Sun, 2 Nov 2003 23:35:34 +0100 From: Diederik van Arkel dvanarkel@mac.com Subject: [clean-list] Question about uniqueness type error On Sunday, November 2, 2003, at 10:51 PM, Jeremy Shaw wrote: > Hello, > > I am getting a uniqueness error I can not explain when I try to > combine type synonyms and classes. I can't figure out if I am > misunderstanding something, or if it is a compiler bug. Section 6.11 of the Clean Language Report states: It is not allowed to use a type synonym as instance. so it's not actually a bug. I would consider it a bug that the compiler doesn't generate an error for this. Regards, Diederik van Arkel From bfulgham@debian.org Sun, 2 Nov 2003 20:16:30 -0800 Date: Sun, 2 Nov 2003 20:16:30 -0800 From: Brent A. Fulgham bfulgham@debian.org Subject: [clean-list] Clean 2.1.0 available for Windows, Mac, Linux and Solaris On Friday 31 October 2003 3:02 am, Clean Support wrote: > Clean 2.1.0 is now available for Windows, Mac OS X, Linux (Intel) > and Solaris (Sparc) at > A precompiled x86 build for Debian GNU/Linux is now available at http://people.debian.org/~bfulgham/clean Enjoy! -Brent From arjenw@cs.kun.nl Mon, 03 Nov 2003 09:49:43 +0100 Date: Mon, 03 Nov 2003 09:49:43 +0100 From: Arjen van Weelden arjenw@cs.kun.nl Subject: [clean-list] Question about uniqueness type error Hi, Attributing the synonym types with '*', instead of '.', also works. This states that these types must always be unique, which does not look like a problem in your example. :: *MonoFrames a :== *{#a} :: *StereoFrames a :== *(*{#a}, *{#a}) :: *Stream a = MonoStream *(MonoFrames a) | StereoStream *(StereoFrames a) Could be a compiler bug, if it cannot deduce uniqueness when you use type synonyms with '.', and it can if you use '*' or no type synonyms. On another hand, type synonyms do not always do what you think they should do. Especially when using classes and/or uniqueness attributes. kind regards, Arjen Jeremy Shaw wrote: > Hello, > > I am getting a uniqueness error I can not explain when I try to > combine type synonyms and classes. I can't figure out if I am > misunderstanding something, or if it is a compiler bug. > > The following code is based on some actually code I wrote, but with > all the irrelevant stuff stripped out for readability. > > -----> > > module test > > import StdEnv > > :: MonoFrames a :== .{#a} > :: StereoFrames a :== .(.{#a},.{#a}) > > :: Stream a = MonoStream .(MonoFrames a) > | StereoStream .(StereoFrames a) > > class Frames a where > mixInFrames :: *a *a -> *a > > instance Frames (MonoFrames *Int) where > mixInFrames :: *(MonoFrames *Int) *(MonoFrames *Int) -> *(MonoFrames *Int) > mixInFrames frames1 frames2 = frames2 > > // This variation does not work > instance Frames (StereoFrames *Int) where > mixInFrames :: *(StereoFrames *Int) *(StereoFrames *Int) -> *(StereoFrames *Int) > mixInFrames (f1l, f1r) (f2l, f2r) = (f2l, f2r) > > /* > // This one works > instance Frames (*{#*Int},*{#*Int}) where > mixInFrames :: *(*{#*Int},*{#*Int}) *(*{#*Int},*{#*Int}) -> *(*{#*Int},*{#*Int}) > mixInFrames (f1l, f1r) (f2l, f2r) = (f2l, f2r) > */ > > // so does this > mixInFrames2 :: *(StereoFrames *Int) *(StereoFrames *Int) -> *(StereoFrames *Int) > mixInFrames2 (f1l, f1r) (f2l, f2r) = (f2l, f2r) > > > mixInStream :: *(Stream *Int) *(Stream *Int) -> *(Stream *Int) > mixInStream (MonoStream frames1) (MonoStream frames2) = (MonoStream (mixInFrames frames1 frames2)) > mixInStream (StereoStream frames1) (StereoStream frames2) = (StereoStream (mixInFrames frames1 frames2)) > > Start = "Hello, World!" > > <----- > > If I try to compile the code as shown, I get the following error: > > clm test -o test > Compiling test > Uniqueness error [test.icl,36,mixInStream]:"argument 1 of StereoStream" attribute at indicated position could not be coerced *(^ {#*Int},{#*Int}) > Uniqueness error [test.icl,36,mixInStream]:"argument 2 of mixInFrames" attribute at indicated position could not be coerced *(StereoFrames ^ *Int) > Uniqueness error [test.icl,36,mixInStream]:"argument 1 of mixInFrames" attribute at indicated position could not be coerced *(StereoFrames ^ *Int) > make: *** [test] Error 1 > > If I comment out this instance: > instance Frames (StereoFrames *Int) > > And uncomment this instance: > instance Frames (*{#*Int},*{#*Int}) > > The code compiles without any errors. OR, if I change mixInStream to > call mixInFrames2, it also compiles fine. > > So I am confused. > > How come mixInFrames2 works, but the 'instance Frames > (StereoFrames *Int)' gives a uniqueness error. > > Am I correct in thinking that: > > mixInFrames :: *(StereoFrames *Int) *(StereoFrames *Int) -> *(StereoFrames *Int) > > is a type synonym for: > > mixInFrames :: *(*{#*Int},*{#*Int}) *(*{#*Int},*{#*Int}) -> *(*{#*Int},*{#*Int}) > > Thanks. > Jeremy Shaw. > > ps. I tested this with clean 2.1 for linux. > > > _______________________________________________ > clean-list mailing list > clean-list@cs.kun.nl > http://www.cs.kun.nl/mailman/listinfo/clean-list From alan_carlyle@iprimus.com.au Mon, 3 Nov 2003 23:58:20 +1100 Date: Mon, 3 Nov 2003 23:58:20 +1100 From: Alan Carlyle alan_carlyle@iprimus.com.au Subject: [clean-list] A minor issue with usability? Hi All! I've recently returned to using Clean after a few years hiatus; mainly as an antidote to the .NET development I earn a living with ;} Now that I've returned I am surprised to see that a rather ugly 'feature' has not been corrected. Namely the "press any key to exit" and intrusive pause this forces on us for programs compiled for the console. This is a major problem as it prevents me from using Clean to write small, fast programs with output that can be run in scripts i.e. Bash (Cygwin & Linux) and Win' Batch files. It also prevents the elegant use of Clean programs as functional ( ;-) ) building blocks, where one program streams it's output as input to another, as is often done with the Unix/GNU set of simple program development tools. With the "press any key to exit" feature it is all but impossible to write a program that will execute the same and present the user with _exactly_ the same behaviour as the very simple C program below: /*BOF*/ /* Compiled under cygwin on XP Pro using GNU gcc.*/ #include int main() { printf("Hello Clean.\n"); printf("\tCatch me if you can...."); return 0; } /*EOF*/ This is a _BIG_ drawback to the widespread use of Clean. I was keen on the idea of rewriting some of the GNU tools in Clean (just for the fun of it) e.g. wc, sort, uniq, cut, tr, head, tail, diff, patch, cvs, ... Yet with the "press any key to exit" feature it isn't even possible to write a program that does exactly the same thing as this; wc --help I also had in mind a personal project of extending Clean's functionality down closer to the OS, with the goal of reaching a level where it isn't necessary to write auxilliary low level support in C. Sorry to go on a bit but this is IMHO a serious problem which is preventing an otherwise wonderful language from proving to all those Turing machines out there that Turing was right when he said his theory and Church's were equivalent and equally powerful. Let's see if this can be proved in practice as well as theory!! Could the developers of Clean please remove/optionalise this feature, and if possible, supply a patch we can apply to our current versions. Kind Regards, Alan Carlyle P.S. If there are any Moral, Ethical, Legal, Religous or other historical reasons for the current state of affairs I would be very interested in knowing what thay may be and apologise in advance for any offence I may have caused. From arjenw@cs.kun.nl Mon, 03 Nov 2003 15:08:03 +0100 Date: Mon, 03 Nov 2003 15:08:03 +0100 From: Arjen van Weelden arjenw@cs.kun.nl Subject: [clean-list] A minor issue with usability? Alan Carlyle wrote: > Hi All! > > I've recently returned to using Clean after a few years hiatus; mainly as an > antidote to the .NET development I earn a living with ;} > > Now that I've returned I am surprised to see that a rather ugly 'feature' > has not been corrected. Namely the "press any key to exit" and intrusive > pause this forces on us for programs compiled for the console. > Hi Alan, Here is a hack (for Windows) that removes the "press any key", and allows redirection at the command line. Remember to select the 'No Return Type' project option in the CleanIDE. // Project options: use No Return Type import StdFile setConsoleFlag :: !*World -> *World setConsoleFlag _ = code { pushL _console_flag pushI -4 addI push_b_a 0 pop_b 1 pushI 1 fill1_r _ 0 1 0 01 .keep 0 1 pop_a 1 fill_a 0 1 pop_a 1 } stdOut :: !String !*World -> *World stdOut msg world # world = setConsoleFlag world (console, world) = stdio world console = fwrites msg console (_, world) = fclose console world = world Start :: *World -> *World Start world = stdOut "Hello C.\n\tCaught you!" world kind regards, Arjen From vissers@theochem.kun.nl Tue, 4 Nov 2003 10:56:13 +0100 (CET) Date: Tue, 4 Nov 2003 10:56:13 +0100 (CET) From: G.W.M. Vissers vissers@theochem.kun.nl Subject: [clean-list] Clean 2.1 cosh I notice the cosh bug has not been fixed in Clean 2.1, i.e. cosh = 0.5 * (exp(x) + exp(~x)) and not 2.0*(exp(x) + exp(~x)) cheers, G From pieter@cs.kun.nl Tue, 04 Nov 2003 17:25:56 +0100 Date: Tue, 04 Nov 2003 17:25:56 +0100 From: Pieter Koopman pieter@cs.kun.nl Subject: [clean-list] Clean 2.1 cosh Dear Ge Vissers, At 10:56 04-11-2003 +0100, G.W.M. Vissers wrote: >I notice the cosh bug has not been fixed in Clean 2.1, i.e. > >cosh = 0.5 * (exp(x) + exp(~x)) > >and not 2.0*(exp(x) + exp(~x)) We are very sorry. It seems to be fixed in the Mac and Windows versions, but we failed to transfer this correction to Linux and Solaris. We will try again in the next release. Thank you very much for reporting this bug, Pieter Koopman The University of Nijmegen will be named Radboud University Nijmegen as of September 1st, 2004 From brent.fulgham@xpsystems.com Mon, 10 Nov 2003 10:19:44 -0800 Date: Mon, 10 Nov 2003 10:19:44 -0800 From: Brent Fulgham brent.fulgham@xpsystems.com Subject: [clean-list] "Concurrent" Clean Where would I find information on the "Concurrent" aspects of Clean? Are there threading primitives, or some notion of coroutines that are documented somewhere? A cursory look at the manual doesn't register anything, but it's still early Monday morning here, so I may just need a refill of my tea. -Brent From rinus@cs.kun.nl Tue, 11 Nov 2003 00:09:18 +0100 Date: Tue, 11 Nov 2003 00:09:18 +0100 From: Rinus Plasmeijer rinus@cs.kun.nl Subject: [clean-list] "Concurrent" Clean Dear Brent, Clean used to be Concurrent, but we dropped the feature due to lack off parallel machines. However, in the typed functional operating system of Arjen van Weelden, one can define and control processes again. The system features a typed shell as well. The shell command language is a simple but complete typed functional language. Files are typed. Most functions from Clean standard environment have been stored in files. The shell has the look and feel of an interpreter for a functional language, but it actually just combines compiled code. Have a look at the system. You can download it from http://www.cs.kun.nl/~arjenw/ greetings, Rinus ----- Original Message ----- From: "Brent Fulgham" To: "Clean List" Sent: Monday, November 10, 2003 7:19 PM Subject: [clean-list] "Concurrent" Clean > Where would I find information on the "Concurrent" aspects of Clean? Are there threading primitives, or some notion of coroutines that are documented somewhere? A cursory look at the manual doesn't register anything, but it's still early Monday morning here, so I may just need a refill of my tea. > > -Brent > > > > _______________________________________________ > clean-list mailing list > clean-list@cs.kun.nl > http://www.cs.kun.nl/mailman/listinfo/clean-list > From m.verver@student.utwente.nl Tue, 11 Nov 2003 00:20:29 +0100 Date: Tue, 11 Nov 2003 00:20:29 +0100 From: Maks Verver m.verver@student.utwente.nl Subject: [clean-list] "Concurrent" Clean Hi Brent, On Monday 10 November 2003 19:19, Brent Fulgham wrote: > Where would I find information on the "Concurrent" aspects of Clean? Are > there threading primitives, or some notion of coroutines that are > documented somewhere? A cursory look at the manual doesn't register > anything, but it's still early Monday morning here, so I may just need a > refill of my tea. To my understanding, you have had the right amount of tea, and no form of concurrency control is present in the current version of "Concurrent" Clean. This issue has come up earlier on the mailing list and I took the liberty of digging it up from the archives: >From F.S.A.Zuurbier@inter.nl.net Tue, 7 May 2002 06:55:57 UT: > Jafar wrote: > > I am looking for a concurrent programming language to > > implement some mobile agent simulation. I skimmed > > through the pdf documents that come with the Clean > > download, as well as the language report, but I could > > not find anything that said directly: "Clean can be > > used to make concurrent processes." I believe that it > > can be done, but I would like confirmation before I go > > about studying the language. If it can be done, what > > is the maximum number of concurrent processes that can > > be programmed? > 'Concurrent' has been in the name for years now. There have been attempts in > the past to really implement this, but current versions of the language - > outside the laboratory - don't support parallelism or even interleaved > processing. The attempts aimed at concurrency that was indicated to the > compiler by annotations. The annotation {P} would indicate that the > following expression was to be evaluated on a different processor. > {I} meant that the expression was to be evaluated in an interleaved way > on the same processor. Although this has advantages also on a > semantic level, I believe itis very low (if at all) on Nijmegen's > priority list. > > Regards Erik Zuurbier > Kind regards, Maks Verver. From hugorufino@yahoo.com Tue, 11 Nov 2003 10:05:08 -0300 (ART) Date: Tue, 11 Nov 2003 10:05:08 -0300 (ART) From: =?iso-8859-1?q?Hugo=20Rufino?= hugorufino@yahoo.com Subject: [clean-list] How to play a MIDI file ... --0-1659214612-1068555908=:90461 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit Hello Cleaners!! I've some files *.mid and want to play them. I would like to do the following: 1 - Open an explorer window, select the file xxx.mid and the Clean play it!! Does anyone know how can I do it?? Thanks in advance for any answer, Hugo --------------------------------- Yahoo! Mail - 6MB, anti-spam e antivírus gratuito. Crie sua conta agora! --0-1659214612-1068555908=:90461 Content-Type: text/html; charset=iso-8859-1 Content-Transfer-Encoding: 8bit
Hello Cleaners!!
 
I've some files *.mid and want to play them. I would like to do the following:
1 - Open an explorer window, select the file xxx.mid and the Clean play it!!
 
Does anyone know how can I do it??
 
Thanks in advance for any answer,
 
Hugo



Yahoo! Mail - 6MB, anti-spam e antivírus gratuito. Crie sua conta agora! --0-1659214612-1068555908=:90461-- From willeralves@yahoo.com.br Tue, 11 Nov 2003 12:50:31 -0300 (ART) Date: Tue, 11 Nov 2003 12:50:31 -0300 (ART) From: =?iso-8859-1?q?Alves=20da=20Silva=20Cruz=20Willer?= willeralves@yahoo.com.br Subject: [clean-list] How to play a MIDI file ... --0-1501462701-1068565831=:11106 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit Hi Hugo! I don't know exactly how it works but you could give a look at the worms source code (Examples/Game Examples 1.2.2/Worms). It looks like it plays both MIDI and WAVE formats. Maybe this could give you some idea... See you... Willer Alves Uberlândia, MG - Brazil Hugo Rufino wrote: Hello Cleaners!! I've some files *.mid and want to play them. I would like to do the following: 1 - Open an explorer window, select the file xxx.mid and the Clean play it!! Does anyone know how can I do it?? Thanks in advance for any answer, Hugo --------------------------------- Yahoo! Mail - 6MB, anti-spam e antivírus gratuito. Crie sua conta agora! --------------------------------- Yahoo! Mail - 6MB, anti-spam e antivírus gratuito. Crie sua conta agora! --0-1501462701-1068565831=:11106 Content-Type: text/html; charset=iso-8859-1 Content-Transfer-Encoding: 8bit
Hi Hugo!
 
I don't know exactly how it works but you could give a look at the worms source code (Examples/Game Examples 1.2.2/Worms). It looks like it plays both MIDI and WAVE formats. Maybe this could give you some idea...
 
See you...
 
Willer Alves
Uberlândia, MG - Brazil
 

Hugo Rufino <hugorufino@yahoo.com> wrote:
Hello Cleaners!!
 
I've some files *.mid and want to play them. I would like to do the following:
1 - Open an explorer window, select the file xxx.mid and the Clean play it!!
 
Does anyone know how can I do it??
 
Thanks in advance for any answer,
 
Hugo



Yahoo! Mail - 6MB, anti-spam e antivírus gratuito. Crie sua conta agora!



Yahoo! Mail - 6MB, anti-spam e antivírus gratuito. Crie sua conta agora! --0-1501462701-1068565831=:11106-- From jeremy.shaw@lindows.com Tue, 11 Nov 2003 10:21:42 -0800 Date: Tue, 11 Nov 2003 10:21:42 -0800 From: Jeremy Shaw jeremy.shaw@lindows.com Subject: [clean-list] How to play a MIDI file ... Hello, You could also look at Q and Q-MIDI as a starting point: http://www.musikwissenschaft.uni-mainz.de/~ag/q/q.php Jeremy Shaw At Tue, 11 Nov 2003 10:05:08 -0300 (ART), Hugo Rufino wrote: > > [1 ] > Hello Cleaners!! > > I've some files *.mid and want to play them. I would like to do the following: > 1 - Open an explorer window, select the file xxx.mid and the Clean play it!! > > Does anyone know how can I do it?? > > Thanks in advance for any answer, > > Hugo > > > > --------------------------------- > Yahoo! Mail - 6MB, anti-spam e antivírus gratuito. Crie sua conta agora! > [2 ] > From pauldv@cs.kun.nl Wed, 12 Nov 2003 10:20:44 +0100 Date: Wed, 12 Nov 2003 10:20:44 +0100 From: Paul de Vrieze pauldv@cs.kun.nl Subject: [clean-list] How to play a MIDI file ... -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Tuesday 11 November 2003 16:50, Alves da Silva Cruz Willer wrote: > Hi Hugo! > > I don't know exactly how it works but you could give a look at the > worms source code (Examples/Game Examples 1.2.2/Worms). It looks like > it plays both MIDI and WAVE formats. Maybe this could give you some > idea... > Also on the windows platform midi is one of the standard formats. That means you can just use a system call to tell windows to play it. Paul - -- Paul de Vrieze Researcher Mail: pauldv@cs.kun.nl Homepage: http://www.cs.kun.nl/~pauldv -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.3 (GNU/Linux) iD8DBQE/sft4Nb2zbbdIrucRAuI/AJ9mmUN5wJecCUdpGG8IEUTAyEJJvgCfXgvN B3Fu4m6dkdJ+Fn/hHcDnqWg= =zKcJ -----END PGP SIGNATURE----- From willeralves@yahoo.com.br Thu, 13 Nov 2003 10:16:38 -0300 (ART) Date: Thu, 13 Nov 2003 10:16:38 -0300 (ART) From: =?iso-8859-1?q?Alves=20da=20Silva=20Cruz=20Willer?= willeralves@yahoo.com.br Subject: [clean-list] External programs --0-432695181-1068729398=:81907 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit Hello all, I'm triyng to develop an application in Clean that involves video streaming and I need to know if there is a way to open a streaming player (QuickTime, Windows Media Player or Real Player) inside an Object IO Clean Interface. I know I can launch an external application from Clean but can I launch this application inside a Clean window? I need this to work just like when Internet browsers opens a player inside their own window. Has someone tried this ou could give me any advice? Thanks in advance. Willer Alves Uberlandia, MG - Brazil --------------------------------- Yahoo! Mail - 6MB, anti-spam e antivírus gratuito. Crie sua conta agora! --0-432695181-1068729398=:81907 Content-Type: text/html; charset=iso-8859-1 Content-Transfer-Encoding: 8bit
Hello all,
 
I'm triyng to develop an application in Clean that involves video streaming and I need to know if there is a way to open a streaming player (QuickTime, Windows Media Player or Real Player) inside an Object IO Clean Interface. I know I can launch an external application from Clean but can I launch this application inside a Clean window? I need this to work just like when Internet browsers opens a player inside their own window.
 
Has someone tried this ou could give me any advice?
 
Thanks in advance.
 
Willer Alves
Uberlandia, MG - Brazil



Yahoo! Mail - 6MB, anti-spam e antivírus gratuito. Crie sua conta agora! --0-432695181-1068729398=:81907-- From karczma@info.unicaen.fr Fri, 14 Nov 2003 10:13:25 +0100 Date: Fri, 14 Nov 2003 10:13:25 +0100 From: Jerzy Karczmarczuk karczma@info.unicaen.fr Subject: [clean-list] Playing sounds As you noticed, someone will use Clean for video streaming. Nice to see the Clean List back to life. So, just to make some noise, I have a question. About making noise. Under Windows. The StdSound module in the last Clean is truncated, the call to WinSoundPlay is commented out, 'playSoundFile' doesn't do anything. Why? WinSOundPlay exists of course, this is an inline code. Everything finally goes to the winmm.dll, PlaySoundA@12. Ugh. "The buck stops here"... The games use more involved, a little tagliatelle-style chain of calls to sound events. I scanned all that, but finally I gave up. Perhaps somebody could help me? I would like to play a sound (wave pattern) directly from an internal buffer. Passing to some Windows obscure demons *just* * the address of the buffer * its length * number of channels (or not, mono is good enough) * sampling ratio (items/sec of audio rendering) * bits/item (8 or 16; or not. 16 by default, let's be serious...) And *nothing* more. All that belongs to the canonical .wav format. I might at the beginning try to recreate from some internal highly esoteric DSP procedures a .wav output and to play it back, but I *need* finally to have it online. I want to code in a purely functional way a pedagogic sound sythesizer. A low- level synthesizer, no need to remind me that such things as Haskore exist... (And don't need to mention the Common Lisp Music; it is all *but* purely functional). Does somebody (Mike Wiering, perhaps) has some experience with that? Did somebody try to work on Clean bindings of the DirectSound stuff? I know that there are Windows APIs permitting to pass some memory image of a wave pattern to the 'player', but I am - for the moment - hopelessly ignorant [after all, I am just a phys/math-oriented theoretician, sacré bleu...] and you might spare me some cruel suffering. Perhaps you know of a simple external library, available with sources, which uses standard Windows APIs for the sound generation, so that I could calque it, and plug into Clean I/O? Thank you. Jerzy Karczmarczuk Caen, France From ronny@cs.kun.nl Mon, 17 Nov 2003 09:57:26 +0100 Date: Mon, 17 Nov 2003 09:57:26 +0100 From: Ronny Wichers Schreur ronny@cs.kun.nl Subject: [clean-list] Playing sounds Jerzy Karczmarczuk writes (to the Clean discussion list): > The StdSound module in the last Clean is truncated, the call > to WinSoundPlay is commented out, 'playSoundFile' doesn't do > anything. Why? StdSound is a platform-independent module, so it doesn't look right to call a Windows API function there. And if I look at Peter's comment for this change is: "(PA) Uniform Object I/O dd.29 juni '01.", where uniform means Mac/Windows. > WinSOundPlay exists of course, this is an inline code. Everything > finally goes to the winmm.dll, PlaySoundA@12. Ugh. "The buck > stops here"... My guess is that if you remove the comment it will just work (only on Windows, of course). Cheers, Ronny Wichers Schreur From karczma@info.unicaen.fr Tue, 18 Nov 2003 12:06:35 +0100 Date: Tue, 18 Nov 2003 12:06:35 +0100 From: Jerzy Karczmarczuk karczma@info.unicaen.fr Subject: [clean-list] Playing sounds Ronny Wichers Schreur wrote: > Jerzy Karczmarczuk writes (to the Clean discussion list): > >> The StdSound module in the last Clean is truncated, the call >> to WinSoundPlay is commented out, 'playSoundFile' doesn't do >> anything. Why? ... > Peter's comment for this change is: "(PA) Uniform Object I/O dd.29 > juni '01.", where uniform means Mac/Windows. > >> WinSOundPlay exists of course, this is an inline code. Everything >> finally goes to the winmm.dll, PlaySoundA@12. Ugh. "The buck >> stops here"... > > > My guess is that if you remove the comment it will just work (only > on Windows, of course). Alright, plus some superficial bugs such as WinSoundPlay =-=> winSoundPlay... Thank you, I discovered that. So I might in principle generate a binary .wav file and to play it after having read it back. But my *MAIN* problem persists : how to play from an internal buffer... How to do it asynchronously? Can't really anybody there help me? This is really frustrating... Jerzy Karczmarczuk From Jeremy.Shaw@lindows.com Tue, 18 Nov 2003 08:02:51 -0800 (PST) Date: Tue, 18 Nov 2003 08:02:51 -0800 (PST) From: Jeremy Shaw Jeremy.Shaw@lindows.com Subject: [clean-list] Playing sounds Hello, Have you considering writing some (partial) bindings for SDL? http://www.libsdl.org/index.php Looking at this page, I think it would be fairly trivial: http://sdldoc.csn.ul.ie/guideaudioexamples.php I think you would only need call the following functions: SDL_Init (not shown on that page). SDL_OpenAudio SDL_MixAudio SDL_PauseAudio SDL_CloseAudio SDL_Delay I think you will find the SDL interface much easier to use that trying to call OS specific code, and as an added benefit, SDL is ported to linux, win32, MacOS, MacOS X, BeOS, and unofficially ported to Solaris, IRIX, FreeBSD, QNX, OSF/True64. I hope to write a full set of bindings for clean and SDL someday. SDL already has an impressive number of bindings: http://www.libsdl.org/languages.php Jeremy Shaw. On Nov 18, 2003 3:06 AM, Jerzy Karczmarczuk wrote: > Ronny Wichers Schreur wrote: > > Jerzy Karczmarczuk writes (to the Clean discussion list): > > > >> The StdSound module in the last Clean is truncated, the call > >> to WinSoundPlay is commented out, 'playSoundFile' doesn't do > >> anything. Why? > ... > > Peter's comment for this change is: "(PA) Uniform Object I/O dd.29 > > juni '01.", where uniform means Mac/Windows. > > > >> WinSOundPlay exists of course, this is an inline code. Everything > >> finally goes to the winmm.dll, PlaySoundA@12. Ugh. "The buck > >> stops here"... > > > > > > My guess is that if you remove the comment it will just work (only > > on Windows, of course). > > Alright, plus some superficial bugs such as WinSoundPlay =-=> winSoundPlay... > Thank you, I discovered that. So I might in principle generate a binary .wav > file and to play it after having read it back. > > But my *MAIN* problem persists : how to play from an internal buffer... How to > do it asynchronously? > > Can't really anybody there help me? This is really frustrating... > > > Jerzy Karczmarczuk > > > > > > > _______________________________________________ > clean-list mailing list > clean-list@cs.kun.nl > http://www.cs.kun.nl/mailman/listinfo/clean-list From karczma@info.unicaen.fr Wed, 19 Nov 2003 10:11:25 +0100 Date: Wed, 19 Nov 2003 10:11:25 +0100 From: Jerzy Karczmarczuk karczma@info.unicaen.fr Subject: [clean-list] Playing sounds Jeremy Shaw wrote: > Hello, > > Have you considering writing some (partial) bindings for SDL? > > http://www.libsdl.org/index.php > > Looking at this page, I think it would be fairly trivial: > > http://sdldoc.csn.ul.ie/guideaudioexamples.php Well, I happen to know SDL, since I taught Python and I used PyGame for some image processing. I might try to look further, but for me SDL was always a comprehensive factory, quite rich... Thank you. Are you sure that it is "trivial"? There is a lot of manipulating of shared data structures, files, etc., and I am not sure yet how to organize all that without breaking Clean. But I like to live dangerously, we'll see... Jerzy Karczmarczuk From johnvg@cs.kun.nl Wed, 19 Nov 2003 11:16:07 +0100 Date: Wed, 19 Nov 2003 11:16:07 +0100 From: John van Groningen johnvg@cs.kun.nl Subject: [clean-list] Playing sounds Jerzy Karczmarczuk writes: >lright, plus some superficial bugs such as WinSoundPlay =-=> winSoundPlay... >Thank you, I discovered that. So I might in principle generate a binary .wav >file and to play it after having read it back. > >But my *MAIN* problem persists : how to play from an internal buffer... How to >do it asynchronously? There is a windows waveOut interface tutorial at: http://www.insomniavisions.com/documents/tutorials/wave.php or: http://www.pscode.com/vb/scripts/ShowCode.asp?txtCodeId=4422&lngWId=3 It includes C source code to play a wav file using buffers of 8k. Adding a Clean interface for this code should not be that much work. Regards, John van Groningen From jeremy.shaw@lindows.com Wed, 19 Nov 2003 10:35:39 -0800 Date: Wed, 19 Nov 2003 10:35:39 -0800 From: Jeremy Shaw jeremy.shaw@lindows.com Subject: [clean-list] Playing sounds Hello, Looking more closely, I see that things are indeed a bit harder than I initially thought. I did not notice the use of callbacks -- that definately makes things harder. I hope to write some clean bindings for the SDL audio interface this weekend for one of my own projects -- but I may not have time until next weekend. I will certainly make a post, if and when I get something working. Jeremy Shaw. At Wed, 19 Nov 2003 10:11:25 +0100, Jerzy Karczmarczuk wrote: > > Jeremy Shaw wrote: > > Hello, > > > > Have you considering writing some (partial) bindings for SDL? > > > > http://www.libsdl.org/index.php > > > > Looking at this page, I think it would be fairly trivial: > > > > http://sdldoc.csn.ul.ie/guideaudioexamples.php > > > Well, I happen to know SDL, since I taught Python and I used PyGame for some > image processing. I might try to look further, but for me SDL was always a > comprehensive factory, quite rich... Thank you. > > > Are you sure that it is "trivial"? There is a lot of manipulating of shared > data structures, files, etc., and I am not sure yet how to organize all that > without breaking Clean. But I like to live dangerously, we'll see... > > > Jerzy Karczmarczuk > > > > > _______________________________________________ > clean-list mailing list > clean-list@cs.kun.nl > http://www.cs.kun.nl/mailman/listinfo/clean-list From willeralves@yahoo.com.br Wed, 19 Nov 2003 13:46:34 -0300 (ART) Date: Wed, 19 Nov 2003 13:46:34 -0300 (ART) From: =?iso-8859-1?q?Alves=20da=20Silva=20Cruz=20Willer?= willeralves@yahoo.com.br Subject: [clean-list] Troubles about Vectors --0-366060412-1069260394=:47678 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit Hello Cleaners, I've been working on a single DFT implementation but I've got in some troubles regarding vectors. Clean returns a share error, wich I can't understand and solve. The error message is something like this: "some" demanded attribute cannot be offered by shared object. The testing code follows below. Has someone know what could be wrong with this code? module test import StdEnv Start = DFT 1 8 { 1.0 \\ i <- [1..8] } { 0.0 \\ i <- [1..8] } DFT :: !Int !Int *{#Real} *{#Real} -> (*{#Real},*{#Real}) DFT dir m x1 y1 #! m = size x1 # x2 = { 0.0 \\ i <- [1..m] } # y2 = { 0.0 \\ i <- [1..m] } # (x2,y2) = loop1 0 m dir x1 y1 x2 y2 | dir == 1 = ({ x/(toReal m) \\ x <-: x2},{ y/(toReal m) \\ y <-: y2}) | otherwise = (x2,y2) where loop1 :: Int !Int !Int *{#Real} *{#Real} *{#Real} *{#Real} -> (*{#Real},*{#Real}) loop1 i m dir x1 y1 x2 y2 | i == m = (x2,y2) #! x2 = {x2 & [i]=0.0} #! y2 = {y2 & [i]=0.0} #! arg = (~(toReal dir))*2.0*3.141592654*(toReal i)/(toReal m) # (x2,y2) = loop2 i 0 m arg x1 y1 x2 y2 = loop1 (i+1) m dir x1 y1 x2 y2 loop2 :: Int Int !Int !Real *{#Real} *{#Real} *{#Real} *{#Real} -> (*{#Real},*{#Real}) loop2 i k m arg x1 y1 x2 y2 | k == m = (x2,y2) #! cosarg = cos ((toReal k)*arg) #! sinarg = sin ((toReal k)*arg) #! auxx = x2.[i] #! auxy = y2.[i] #! vx = x1.[k] #! vy = y1.[k] = loop2 i (k+1) m arg x1 y1 {x2 & [i]=(auxx + (vx*cosarg - vy*sinarg))} {y2 & [i]=(auxy + (vx*sinarg + vy*cosarg))} Thanks in advance, Willer Alves Uberlândia, MG - Brazil --------------------------------- Yahoo! Mail - 6MB, anti-spam e antivírus gratuito. Crie sua conta agora! --0-366060412-1069260394=:47678 Content-Type: text/html; charset=iso-8859-1 Content-Transfer-Encoding: 8bit
Hello Cleaners,
 
I've been working on a single DFT implementation but I've got in some troubles regarding vectors. Clean returns a share error, wich I can't understand and solve. The error message is something like this:
 
"some" demanded attribute cannot be offered by shared object.
 
The testing code follows below. Has someone know what could be wrong with this code?
 
module test
import StdEnv
 
Start = DFT 1 8 { 1.0 \\ i <- [1..8] } { 0.0 \\ i <- [1..8] }
DFT :: !Int !Int *{#Real} *{#Real} -> (*{#Real},*{#Real})
DFT dir m x1 y1
#! m = size x1
# x2 = { 0.0 \\ i <- [1..m] }
# y2 = { 0.0 \\ i <- [1..m] }
# (x2,y2) = loop1 0 m dir x1 y1 x2 y2
| dir == 1 = ({ x/(toReal m) \\ x <-: x2},{ y/(toReal m) \\ y <-: y2})
| otherwise = (x2,y2)
where
 loop1 :: Int !Int !Int *{#Real} *{#Real} *{#Real} *{#Real} -> (*{#Real},*{#Real})
 loop1 i m dir x1 y1 x2 y2
 | i == m = (x2,y2)
 #! x2 = {x2 & [i]=0.0}
 #! y2 = {y2 & [i]=0.0}
 #! arg = (~(toReal dir))*2.0*3.141592654*(toReal i)/(toReal m)
 # (x2,y2) = loop2 i 0 m arg x1 y1 x2 y2
 = loop1 (i+1) m dir x1 y1 x2 y2
 
 loop2 :: Int Int !Int !Real *{#Real} *{#Real} *{#Real} *{#Real} -> (*{#Real},*{#Real})
 loop2 i k m arg x1 y1 x2 y2
 | k == m = (x2,y2)
 #! cosarg = cos ((toReal k)*arg)
 #! sinarg = sin ((toReal k)*arg)
 #! auxx = x2.[i]
 #! auxy = y2.[i]
 #! vx = x1.[k]
 #! vy = y1.[k]
 = loop2 i (k+1) m arg x1 y1 {x2 & [i]=(auxx + (vx*cosarg - vy*sinarg))} {y2 & [i]=(auxy + (vx*sinarg + vy*cosarg))}
Thanks in advance,
 
Willer Alves
Uberlândia, MG - Brazil



Yahoo! Mail - 6MB, anti-spam e antivírus gratuito. Crie sua conta agora! --0-366060412-1069260394=:47678-- From dvanarkel@mac.com Wed, 19 Nov 2003 23:06:19 +0100 Date: Wed, 19 Nov 2003 23:06:19 +0100 From: Diederik van Arkel dvanarkel@mac.com Subject: [clean-list] Troubles about Vectors On Nov 19, 2003, at 5:46 PM, Alves da Silva Cruz Willer wrote: > Hello Cleaners, >   > I've been working on a single DFT implementation but I've got in some > troubles regarding vectors. Clean returns a share error, wich I can't > understand and solve. The error message is something like this: >   > "some" demanded attribute cannot be offered by shared object. >   The "some" here is the '*' uniqueness attribute. In loop1 you are using x1 and y1 twice in the definition thus they are shared and not unique as your type tries to claim. Solution: either remove the uniqueness attribute or return x1 and y1 from loop2 thus removing the sharing eg. ... # (x1,y1,x2,y2) = loop2 i 0 m arg x1 y1 x2 y2 = loop1 (i+1) m dir x1 y1 x2 y2 loop2 :: Int Int !Int !Real *{#Real} *{#Real} *{#Real} *{#Real} -> (*{#Real},*{#Real},*{#Real},*{#Real}) loop2 i k m arg x1 y1 x2 y2 | k == m = (x1,y1,x2,y2) ... Regards, Diederik van Arkel > The testing code follows below. Has someone know what could be wrong > with this code? >   > module test > import StdEnv >   > Start = DFT 1 8 { 1.0 \\ i <- [1..8] } { 0.0 \\ i <- [1..8] } > DFT :: !Int !Int *{#Real} *{#Real} -> (*{#Real},*{#Real}) > DFT dir m x1 y1 > #! m = size x1 > # x2 = { 0.0 \\ i <- [1..m] } > # y2 = { 0.0 \\ i <- [1..m] } > # (x2,y2) = loop1 0 m dir x1 y1 x2 y2 > | dir == 1 = ({ x/(toReal m) \\ x <-: x2},{ y/(toReal m) \\ y <-: y2}) > | otherwise = (x2,y2) > where >  loop1 :: Int !Int !Int *{#Real} *{#Real} *{#Real} *{#Real} -> > (*{#Real},*{#Real}) >  loop1 i m dir x1 y1 x2 y2 >  | i == m = (x2,y2) >  #! x2 = {x2 & [i]=0.0} >  #! y2 = {y2 & [i]=0.0} >  #! arg = (~(toReal dir))*2.0*3.141592654*(toReal i)/(toReal m) >  # (x2,y2) = loop2 i 0 m arg x1 y1 x2 y2 >  = loop1 (i+1) m dir x1 y1 x2 y2 >   >  loop2 :: Int Int !Int !Real *{#Real} *{#Real} *{#Real} *{#Real} -> > (*{#Real},*{#Real}) >  loop2 i k m arg x1 y1 x2 y2 >  | k == m = (x2,y2) >  #! cosarg = cos ((toReal k)*arg) >  #! sinarg = sin ((toReal k)*arg) >  #! auxx = x2.[i] >  #! auxy = y2.[i] >  #! vx = x1.[k] >  #! vy = y1.[k] >  = loop2 i (k+1) m arg x1 y1 {x2 & [i]=(auxx + (vx*cosarg - > vy*sinarg))} {y2 & [i]=(auxy + (vx*sinarg + vy*cosarg))} > Thanks in advance, From zenem@earthlink.net Wed, 19 Nov 2003 16:17:24 -0800 Date: Wed, 19 Nov 2003 16:17:24 -0800 From: Zeno zenem@earthlink.net Subject: [clean-list] Exercise 2 from Chapter 2 of Clean Book Howdy, The problem is... Finite precision of reals. Execute the start expression given in section 2.4.2. Rewrite the program such that it only prints the smallest number that is different from zero using the function until. The program we must rewrite is... Start = takeWhile ((<>) 0.0) (iterate (\x -> x/10.0) 1.0) ...and this is what I came up with... Start = until((==) 0.0 o (*) 0.1) (\x->x*0.1) 1.0 I did see a previous message about the same problem which directed the poster to http://www.cs.kun.nl/pipermail/clean-list/2001/001639.html . I think I have done what the message says to do, but I do not understand in that post why one version transfers the value to a register before comparison, but the other doesn't. But even so, shouldn't the following work... Start = until((==) 0.0 o (*) 0.00000000001) (\x->x*0.1) 1.0 ...it doesn't, the following works... Start = until((==) 0.1 o (*) 0.1) (\x->x*0.1) 1.0 ---but the following does not work... Start = until((==) 0.01 o (*) 0.1) (\x->x*0.1) 1.0 Can anyone help me with this? Thank you, - Zeno From aondi@fit.edu Wed, 19 Nov 2003 19:45:19 -0500 Date: Wed, 19 Nov 2003 19:45:19 -0500 From: Attila Ondi aondi@fit.edu Subject: [clean-list] questions -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hello everyone, I'm somewhat new to Clean and especially to this list, so please take easy on me :) I have some questions regarding the language: ~ 1) Is there any library for abstract data types? I'm looking for something that provides Hashtables, Perfectly ballanced binary trees and such. I could implement those using the basic types in StdEnv (lists, arrays ans so), but I doubt it will be as efficient as possible and also might not be too reliable. Can I find such a library somewhere? ~ 2) How can I handle Strings easily? There are not too much functions that operate on Strings in StdEnv. What I was trying to acieve is to parse a String according to some format. More specifically I had datatypes ::Icon = I Int Int ::Region = R Int Int Int Int ::Click = M Int Int The input string to process had a "I x y" "R x1 y1 x2 y2" or "M x y" in each line, where the 'x's and 'y's are actual integer numbers. At the end of the parsing I wanted to have three lists with types [Icon], [Region], and [Click] respectively. I could manage to use list comprehension to convert the String to [Char] then use basic toolbox functions to cut the list to "words" along white spaces, then based on the first Char of each input line, parse to the corresponding result list based on toInt. I very much doubt that this is the mmost efficient way to parse a string and convert it to my data types. Unfortunately I cannot change the input to something more conveniant... (The described problem is based on an ACM programming contest problem I'm trying to solve with Clean now.) I was hoping to be able to use a method somewhat similar to Haskell's reads. ~ 3) Why doesn't Clean have an interactive command-line interpreter, just like GHC does for Haskell? Sometimes it would be easier to play with the language via an interactive way. I like Clean better than Haskell (especially because of the Uniqueness types as opposed to Haskell's IO monad), but it seems that it's either less conveniant to use Clean based on the above issues, or (and I hope this is the truth) I was much too incompetent in using the language. Thanks for every help, Attila Ondi -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.0.7 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iQCVAwUBP7wOnh5adN4t/v+OAQKIBgP/fifUr08WzUE/XmFW4ecB5K95iNALDwmp ucvs0NMuhLU5swTy8rRAbjV6pr0cbg66kq2UccakOglNHp1LURpzU1JE07CuRqfp 1zI4+Glg85v4VVmvVnhmH+VP31kkADS/A5Fn6Qef4wuCYrfohAwtZ8BjEsg6iN1B xbmdAbUG/xs= =JKxe -----END PGP SIGNATURE----- From fzuurbie@inter.nl.net Thu, 20 Nov 2003 07:49:56 UT Date: Thu, 20 Nov 2003 07:49:56 UT From: fzuurbie@inter.nl.net fzuurbie@inter.nl.net Subject: [clean-list] Exercise 2 from Chapter 2 of Clean Book This is a multi-part message in MIME format. --_----------=_1069314596113804 Content-Disposition: inline Content-Length: 658 Content-Transfer-Encoding: binary Content-Type: text/plain > Howdy, > > The problem is... > > Finite precision of reals. Execute the start expression given > in section 2.4.2. Rewrite the program such that it only prints > the smallest number that is different from zero using the > function until. > > The program we must rewrite is... > > Start = takeWhile ((<>) 0.0) (iterate (\x -> x/10.0) 1.0) [...] > Can anyone help me with this? > Yes: never use == (or <> for that matter) on Reals The Nijmegen team should consider removing the == instance for Reals For now: skip the exercise, it should never have been in the book in the first place. Regards Erik Zuurbier --_----------=_1069314596113804-- From Jenda@Krynicky.cz Thu, 20 Nov 2003 12:23:53 +0100 Date: Thu, 20 Nov 2003 12:23:53 +0100 From: Jenda Krynicky Jenda@Krynicky.cz Subject: [clean-list] questions From: Attila Ondi > ~ 2) How can I handle Strings easily? There are not too much functions > that operate on Strings in StdEnv. What I was trying to acieve is to > parse a String according to some format. More specifically I had > datatypes ::Icon = I Int Int ::Region = R Int Int Int Int ::Click = M > Int Int > > The input string to process had a "I x y" "R x1 y1 x2 y2" or "M x y" > in each line, where the 'x's and 'y's are actual integer numbers. At > the end of the parsing I wanted to have three lists with types [Icon], > [Region], and [Click] respectively. There's nothing better than regexps for string handling, I'm really surprised there is no regular expression library for Clean. Jenda BTW, I get a JavaScript error Line: 672 Error: 'F_doLoaded' is undefined if I go to http://www.cs.kun.nl/~clean/. ===== Jenda@Krynicky.cz === http://Jenda.Krynicky.cz ===== When it comes to wine, women and song, wizards are allowed to get drunk and croon as much as they like. -- Terry Pratchett in Sourcery From t.zielonka@students.mimuw.edu.pl Thu, 20 Nov 2003 13:39:38 +0100 Date: Thu, 20 Nov 2003 13:39:38 +0100 From: Tomasz Zielonka t.zielonka@students.mimuw.edu.pl Subject: [clean-list] questions On Thu, Nov 20, 2003 at 12:23:53PM +0100, Jenda Krynicky wrote: > > There's nothing better than regexps for string handling... It depends on the kind of handling you do. I often find tools like Parser Combinators easier to use and more powerful. They give better modularity and handle bigger classes of languages. But YMMV. Best regards, Tom -- .signature: Too many levels of symbolic links From fzuurbie@inter.nl.net Thu, 20 Nov 2003 15:06:41 UT Date: Thu, 20 Nov 2003 15:06:41 UT From: fzuurbie@inter.nl.net fzuurbie@inter.nl.net Subject: [clean-list] questions This is a multi-part message in MIME format. --_----------=_106934080134161 Content-Disposition: inline Content-Length: 268 Content-Transfer-Encoding: binary Content-Type: text/plain > There's nothing better than regexps for string handling Until you found out about combinator parsing (type this in in Google or CiteSeer). I have a library based on Koopman's and Rojemo's work (continuation passing style), extended with elaborated error messages. --_----------=_106934080134161-- From Jenda@Krynicky.cz Thu, 20 Nov 2003 17:26:36 +0100 Date: Thu, 20 Nov 2003 17:26:36 +0100 From: Jenda Krynicky Jenda@Krynicky.cz Subject: [clean-list] questions From: fzuurbie@inter.nl.net > > There's nothing better than regexps for string handling > > Until you found out about combinator parsing (type this in in Google > or CiteSeer). I have a library based on Koopman's and Rojemo's work > (continuation passing style), extended with elaborated error messages. If you need to PARSE a more complex expression than definitely the combinator parsing or some other kind of parser is in order. If you just want to extract something from a string or test whether it conforms to some not-too-complex format, then parsers (whether combinator based or any other) are overkill. If e.g. I want to make sure that the stuff entered by the user is a date in YYYY-MM-DD format I definitely do not want to spend twenty cryptic lines writing a parser where /^(\d{4})-(\d{1,2})-(\d{1,2})$/ suffices. (I know you need to make sure the month is between 1 and 12 and the day is reasonable, but you'd do that outside the parser as well.) For certain type of tasks there is not anything better than regexs. For other tasks you need a parser. We should not ignore hacks just because by chainsaw you can cut down a tree quicker. Sometimes all you need is to chop a few logs. Jenda ===== Jenda@Krynicky.cz === http://Jenda.Krynicky.cz ===== When it comes to wine, women and song, wizards are allowed to get drunk and croon as much as they like. -- Terry Pratchett in Sourcery From t.zielonka@students.mimuw.edu.pl Thu, 20 Nov 2003 18:08:11 +0100 Date: Thu, 20 Nov 2003 18:08:11 +0100 From: Tomasz Zielonka t.zielonka@students.mimuw.edu.pl Subject: [clean-list] questions On Thu, Nov 20, 2003 at 05:26:36PM +0100, Jenda Krynicky wrote: > > If e.g. I want to make sure that the stuff entered by the user is a > date in YYYY-MM-DD format I definitely do not want to spend twenty > cryptic lines writing a parser where > /^(\d{4})-(\d{1,2})-(\d{1,2})$/ > suffices. (I know you need to make sure the month is between 1 and 12 > and the day is reasonable, but you'd do that outside the parser as > well.) date = do yyyy <- count 4 digit char '-' mm <- count 2 digit char '-' dd <- count 2 digit return (yyyy, mm, dd) Is it really so long and cryptic? You get reusability and compositionality for free. Best regards, Tom -- .signature: Too many levels of symbolic links From ronny@cs.kun.nl Thu, 20 Nov 2003 18:56:01 +0100 Date: Thu, 20 Nov 2003 18:56:01 +0100 From: Ronny Wichers Schreur ronny@cs.kun.nl Subject: [clean-list] Exercise 2 from Chapter 2 of Clean Book Erik Zuurbier writes (to the Clean discussion list): >The Nijmegen team should consider removing the == instance >for Reals > I disagree. Floating point arithmetic is exactly defined and there's nothing wrong with comparing floating point numbers. The problem is the different precision that is used for floats in and out registers (on x86), and the lack of control a Clean programmer has about this due to compiler optimisations. This is a problem that Clean shares with other languages. I believe the approach GHC takes is to round values after each operation (are there double-rounding issues here?). We could do that, although it's against my Dutch nature to throw something away that you get for free (especially if you have to do extra work for it!). Nothing is solved by removing (==) for Real: the same problems occur when you use (>) in the original takeWhile example. There are other problems with floats in Clean: - (<) is defined in terms of (>) which is wrong for floating point numbers; - cancellations in some hyperbolic functions; - The floating point type should be called Float not Real, the type Real should be reserved for exact real arithmetic. But wait: (==) is not computable for exact reals, so I do agree after all! Cheers, Ronny Wichers Schreur From t.zielonka@students.mimuw.edu.pl Thu, 20 Nov 2003 18:20:04 +0100 Date: Thu, 20 Nov 2003 18:20:04 +0100 From: Tomasz Zielonka t.zielonka@students.mimuw.edu.pl Subject: [clean-list] questions On Thu, Nov 20, 2003 at 06:08:11PM +0100, Tomasz Zielonka wrote: > > date = do > yyyy <- count 4 digit > char '-' > mm <- count 2 digit > char '-' > dd <- count 2 digit > return (yyyy, mm, dd) I hope Clean list subscribers were not offended by me sending Haskell code :) By the way, are there any plans to add the do-notation to Clean (if it's not there already - it's been some time since I used Clean). Best regards, Tom -- .signature: Too many levels of symbolic links From bpr@artisan.com Thu, 20 Nov 2003 09:59:14 -0800 Date: Thu, 20 Nov 2003 09:59:14 -0800 From: Brian Rogoff bpr@artisan.com Subject: [clean-list] questions > > There's nothing better than regexps for string handling > > Until you found out about combinator parsing (type this in in Google or > CiteSeer). I have a library based on Koopman's and Rojemo's work > (continuation passing style), extended with elaborated error messages. I agree that combinator parsing can be a lot nicer, and that regexps have lots of nasty features, but they're so popular as a string manipulation tool that I consider it a deficiency of the libraries that there is no Perl-like (yuck, I said it :) regexp library for Clean. In either case (regexps or combinators), I think it would be a good idea to provide a substring based interface, a-la Hansen or the SML Basis library. These provide a natural way for an FPL to do string processing. Here are some refs http://www-2.cs.cmu.edu/~wjh/papers/subseq.html http://www.standardml.org/Basis/substring.html -- -- Brian From miles@caddr.com Thu, 20 Nov 2003 10:22:16 -0800 Date: Thu, 20 Nov 2003 10:22:16 -0800 From: Miles Egan miles@caddr.com Subject: [clean-list] emacs mode for clean --=-oYv8kxAuzYRlcDLu0YHS Content-Type: text/plain Content-Transfer-Encoding: quoted-printable Is there an emacs mode for editing clean code? --=20 Miles Egan --=-oYv8kxAuzYRlcDLu0YHS Content-Type: application/pgp-signature; name=signature.asc Content-Description: This is a digitally signed message part -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.3 (GNU/Linux) iD8DBQA/vQZYU4Jq/wH1PVERAvvvAJ4z4CsZsapBNoTAevbGR1Sknl2+gwCeLLTu yiANNwAU4VIIV396N2xqZNA= =V6/u -----END PGP SIGNATURE----- --=-oYv8kxAuzYRlcDLu0YHS-- From jeremy.shaw@lindows.com Thu, 20 Nov 2003 15:51:10 -0800 Date: Thu, 20 Nov 2003 15:51:10 -0800 From: Jeremy Shaw jeremy.shaw@lindows.com Subject: [clean-list] emacs mode for clean Hello, I have taken the haskell-mode and made some modifications so that it understands clean better, but its far from complete. If there is interest, I can try to make it publicly available. Jeremy Shaw. At Thu, 20 Nov 2003 10:22:16 -0800, Miles Egan wrote: > > [1 ] > Is there an emacs mode for editing clean code? > > -- > Miles Egan > [2 This is a digitally signed message part ] > From miles@caddr.com Thu, 20 Nov 2003 16:01:11 -0800 Date: Thu, 20 Nov 2003 16:01:11 -0800 From: Miles Egan miles@caddr.com Subject: [clean-list] emacs mode for clean --=-lEP/AqIG4VEgwxp2BlUk Content-Type: text/plain Content-Transfer-Encoding: quoted-printable I'd like to try it. Even just some syntax highlighting would be nice. On Thu, 2003-11-20 at 15:51, Jeremy Shaw wrote: > Hello, >=20 > I have taken the haskell-mode and made some modifications so that it > understands clean better, but its far from complete. If there is > interest, I can try to make it publicly available. >=20 > Jeremy Shaw. >=20 > At Thu, 20 Nov 2003 10:22:16 -0800, > Miles Egan wrote: > >=20 > > [1 ] > > Is there an emacs mode for editing clean code? > >=20 > > --=20 > > Miles Egan > > [2 This is a digitally signed message part ] > >=20 >=20 >=20 > _______________________________________________ > clean-list mailing list > clean-list@cs.kun.nl > http://www.cs.kun.nl/mailman/listinfo/clean-list --=20 Miles Egan --=-lEP/AqIG4VEgwxp2BlUk Content-Type: application/pgp-signature; name=signature.asc Content-Description: This is a digitally signed message part -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.3 (GNU/Linux) iD8DBQA/vVXGU4Jq/wH1PVERAtMQAJwMEisokBpLtZ6CapsneszCLtH3VQCfTDow yQN3Xj6uRbYnCs93nUZRJ/E= =tUnW -----END PGP SIGNATURE----- --=-lEP/AqIG4VEgwxp2BlUk-- From fjh@cs.mu.oz.au Mon, 24 Nov 2003 10:10:58 +1100 Date: Mon, 24 Nov 2003 10:10:58 +1100 From: Fergus Henderson fjh@cs.mu.oz.au Subject: [clean-list] questions On 20-Nov-2003, Tomasz Zielonka wrote: > On Thu, Nov 20, 2003 at 05:26:36PM +0100, Jenda Krynicky wrote: > > > > If e.g. I want to make sure that the stuff entered by the user is a > > date in YYYY-MM-DD format I definitely do not want to spend twenty > > cryptic lines writing a parser where > > /^(\d{4})-(\d{1,2})-(\d{1,2})$/ > > suffices. (I know you need to make sure the month is between 1 and 12 > > and the day is reasonable, but you'd do that outside the parser as > > well.) > > date = do > yyyy <- count 4 digit > char '-' > mm <- count 2 digit > char '-' > dd <- count 2 digit > return (yyyy, mm, dd) > > Is it really so long and cryptic? No! "\d{4}" is cryptic! "yyyy <- count 4 digit" is elegant and reasonably concise without being cryptic. But if you really want to make it as concise as possible, at the expense of readability, like the regexp, it could be a lot more concise: do { y <- count 4 digit; char '-'; m <- count 2 digit; char '-'; d <- count 2 digit; return (y, m, d); } With suitable abbreviations, c = char r = count -- r for "repeat" d = digit you could make it a one-liner: do{yyyy<-r 4 d;c '-';mm<-r 2 d;c '-';dd<-r 2 d;return(yyyy,mm,dd); } But I hope you will agree that such source code compression harms readability and that this code, *just like regexps*, is unnecessarily cryptic. -- Fergus Henderson | "I have always known that the pursuit The University of Melbourne | of excellence is a lethal habit" WWW: | -- the last words of T. S. Garp. From t.zielonka@students.mimuw.edu.pl Mon, 24 Nov 2003 00:13:38 +0100 Date: Mon, 24 Nov 2003 00:13:38 +0100 From: Tomasz Zielonka t.zielonka@students.mimuw.edu.pl Subject: [clean-list] questions On Mon, Nov 24, 2003 at 10:10:58AM +1100, Fergus Henderson wrote: > On 20-Nov-2003, Tomasz Zielonka wrote: > > On Thu, Nov 20, 2003 at 05:26:36PM +0100, Jenda Krynicky wrote: > > > > date = do > > yyyy <- count 4 digit > > char '-' > > mm <- count 2 digit > > char '-' > > dd <- count 2 digit > > return (yyyy, mm, dd) > > > > Is it really so long and cryptic? > > No! "\d{4}" is cryptic! "yyyy <- count 4 digit" is elegant and reasonably > concise without being cryptic. Agreed! > With suitable abbreviations, > > c = char > r = count -- r for "repeat" > d = digit > > you could make it a one-liner: > > do{yyyy<-r 4 d;c '-';mm<-r 2 d;c '-';dd<-r 2 d;return(yyyy,mm,dd); } This one is a bit shorter, but a lot more cryptic :) return(,,)`ap`(4`r`d)`ap`(c '-'>>2`r`d)`ap`(c '-'>>2`r`d) (you have to import Monad(ap)) > But I hope you will agree that such source code compression harms readability > and that this code, *just like regexps*, is unnecessarily cryptic. Sure! Best regards, Tom -- .signature: Too many levels of symbolic links From dvanarkel@mac.com Mon, 24 Nov 2003 00:27:59 +0100 Date: Mon, 24 Nov 2003 00:27:59 +0100 From: Diederik van Arkel dvanarkel@mac.com Subject: [clean-list] Mac Clean feedback wanted With the Christmas and New Years break coming up in a few short weeks I'm looking to gather some feedback on the Macintosh versions of the CleanIde and the Object I/O library. I hope to be able to spend some of the holiday time on fixing and improving these and your guidance on which areas need it most would be appreciated. Hoping to receive lots of feedback, Diederik van Arkel P.S. Sending feedback directly to me is fine, unless you want to discuss aspects on the list. From Jenda@Krynicky.cz Mon, 24 Nov 2003 19:12:59 +0100 Date: Mon, 24 Nov 2003 19:12:59 +0100 From: Jenda Krynicky Jenda@Krynicky.cz Subject: [clean-list] questions From: Fergus Henderson > On 20-Nov-2003, Tomasz Zielonka > wrote: > On Thu, Nov 20, 2003 at 05:26:36PM +0100, Jenda Krynicky > wrote: > > > > If e.g. I want to make sure that the stuff entered by > the user is a > > date in YYYY-MM-DD format I definitely do not want > to spend twenty > > cryptic lines writing a parser where > > > /^(\d{4})-(\d{1,2})-(\d{1,2})$/ > > suffices. (I know you need to > make sure the month is between 1 and 12 > > and the day is reasonable, > but you'd do that outside the parser as > > well.) > > date = do > > yyyy <- count 4 digit > char '-' > mm <- count 2 digit > > char '-' > dd <- count 2 digit > return (yyyy, mm, dd) > > Is > it really so long and cryptic? > > No! "\d{4}" is cryptic! "yyyy <- count 4 digit" is elegant and > reasonably concise without being cryptic. It could have been \d\d\d\d. (Four digits) /^(\d\d\d\d)-(\d\d?)-(\d\d?)$/ Anyway I guess the examples I found were not good, your code is not half as bad as I expected. If I had the choice I'd still use regexps though :-) Everything looks cryptic if you are not used to it. Jenda ===== Jenda@Krynicky.cz === http://Jenda.Krynicky.cz ===== When it comes to wine, women and song, wizards are allowed to get drunk and croon as much as they like. -- Terry Pratchett in Sourcery From miles@caddr.com Mon, 24 Nov 2003 11:08:54 -0800 Date: Mon, 24 Nov 2003 11:08:54 -0800 From: Miles Egan miles@caddr.com Subject: [clean-list] questions --=-DNlhgvAnlAbPLPJUKXC5 Content-Type: text/plain Content-Transfer-Encoding: quoted-printable On Sun, 2003-11-23 at 15:10, Fergus Henderson wrote: > On 20-Nov-2003, Tomasz Zielonka wrote: > > On Thu, Nov 20, 2003 at 05:26:36PM +0100, Jenda Krynicky wrote: > > >=20 > > > If e.g. I want to make sure that the stuff entered by the user is a=20 > > > date in YYYY-MM-DD format I definitely do not want to spend twenty=20 > > > cryptic lines writing a parser where > > > /^(\d{4})-(\d{1,2})-(\d{1,2})$/ > > > suffices. (I know you need to make sure the month is between 1 and 12= =20 > > > and the day is reasonable, but you'd do that outside the parser as=20 > > > well.) > >=20 > > date =3D do > > yyyy <- count 4 digit > > char '-' > > mm <- count 2 digit > > char '-' > > dd <- count 2 digit > > return (yyyy, mm, dd) > >=20 > > Is it really so long and cryptic? >=20 > No! "\d{4}" is cryptic! "yyyy <- count 4 digit" is elegant and reasonab= ly > concise without being cryptic. >=20 > But if you really want to make it as concise as possible, at the expense > of readability, like the regexp, it could be a lot more concise: >=20 > do { y <- count 4 digit; char '-'; m <- count 2 digit; char '-'; > d <- count 2 digit; return (y, m, d); } Does clean support do notation? I couldn't find any mention of it in the docs. --=20 Miles Egan --=-DNlhgvAnlAbPLPJUKXC5 Content-Type: application/pgp-signature; name=signature.asc Content-Description: This is a digitally signed message part -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.3 (GNU/Linux) iD8DBQA/wldEU4Jq/wH1PVERAsXcAKDaSZLZOQ/r3S1O+wh/w0CuDpBAjACeLDnN bRUFTKWh1H9qVYKJ8k6B9F8= =VjOH -----END PGP SIGNATURE----- --=-DNlhgvAnlAbPLPJUKXC5-- From fjh@cs.mu.oz.au Tue, 25 Nov 2003 13:28:36 +1100 Date: Tue, 25 Nov 2003 13:28:36 +1100 From: Fergus Henderson fjh@cs.mu.oz.au Subject: [clean-list] questions On 24-Nov-2003, Miles Egan wrote: > Does clean support do notation? No. The code that I posted was, like that of the poster to whom I was replying, Haskell code. -- Fergus Henderson | "I have always known that the pursuit The University of Melbourne | of excellence is a lethal habit" WWW: | -- the last words of T. S. Garp. From fzuurbie@inter.nl.net Wed, 26 Nov 2003 08:26:19 UT Date: Wed, 26 Nov 2003 08:26:19 UT From: fzuurbie@inter.nl.net fzuurbie@inter.nl.net Subject: [clean-list] Garbage collect databases This is a multi-part message in MIME format. --_----------=_1069835179174412 Content-Disposition: inline Content-Length: 2011 Content-Transfer-Encoding: binary Content-Type: text/plain Dear Cleaners, Back down to earth. Where I work, a system is being developed along the following lines. First there is an ordering data-entry program that checks the entered company code with a relational master data table. Then someone else processes the ordering data and yet another program sends the result to the company mentioned earlier, based on the address in the master data table. Nothing exciting, so what do you think? Of course there is a program to maintain the master data, which introduces the posibility that sending fails: enter ordering data, delete the company and try to send the ordering data. (Please hang on for another minute, I am getting to FP.) First of all, the initial development budget is tight, so this is just how it is being programmed. The failure will simply be dumped on an operator. In a second version someone programs that a company cannot be deleted if there are outstanding orders. Then someone realizes the burden on the operator and the possible starvation: if enough orders are being entered, the company can never be deleted. Therefore a boolean is added to each company record. If the system manager wants to delete a company, s/he sets the boolean to False and the company will no longer be allowed when entering ordering data. Periodically a batch program removes the company records with the boolean set to False, which have no outstanding orders. Things like these happen a thousand times, while it is nothing more than a garbage collection problem. A thousand times operators, analysts and programmers are loaded with work to overcome it. Also system documentation covers the particular garbage collection solution, which is essentially non-information. Now while FP's have adequately solved this garbage collection problem for single executables and their RAM-heap, I am not aware of any practical solution that also garbage collects database records or files. Does anybody know about work in this direction? Regards Erik Zuurbier --_----------=_1069835179174412-- From betsy@cs.kun.nl Wed, 26 Nov 2003 14:02:10 +0100 Date: Wed, 26 Nov 2003 14:02:10 +0100 From: Betsy Pepels betsy@cs.kun.nl Subject: [clean-list] Re: Garbage collect databases Hello Erik, I'd to think for a while about your problem. I'm interested in data modelling and FP (and actually I'm trying to develop a CASE Tool as an addition to Clean). Although your problem looks like a garbage collection problem (or more generally spoken, a run-time or processing problem), I think it is more a data modelling problem. Or if you wish, a data modelling error that is solved in the wrong way. First, as always, little or no difference is made between the data model and its implementation. Like: > Therefore a boolean is added to each company record. Second, deleting records from a table is far from trivial anyhow.You've got to check dependencies (not only dependencies like you describe; one can imagine zillions of situations, like: you can't remove a debtor if he still has to pay debts). Here a good data model is also very useful, because it helps to identify such dependencies. To answer your question (very partially), I think that solving this 'garbage collection' problem at the lowest level (the implementation level) is the wrong way. It is better to identify the dependencies at the data model level and to derive from these the correct processes (for instance for record deletion). In the far, far future, hopefully my tool will generate automatically the checks that have to be made before (the FP equivalent of) a record can be deleted. Look what happened when in your case a correct data model had been developed. (It looks like if that is very expensive, but it prevents such awful repairs afterwards). Then you (hopefully) detect that companies exist in, say, flavours. Companies which are allowed to order, and companies which aren't. Most probably there will be more flavours, like companies which are allowed to order but have to pay beforehand. And to make things even more complicated: companies which are allowed to order as long as their debt doesn't exceed a certain limit. After you have determined that there are such company flavours, you think about an implementation of this. One or more Boolean's could be a solution, but for instance maintaining tables for each flavour is also a possibility. GreetZ, Betsy (guest at Software Technology) ______________________________________________________________ > Reply-To: fzuurbie@inter.nl.net > Subject: [clean-list] Garbage collect databases ..... > Dear Cleaners, > > Back down to earth. Where I work, a system is being developed along the following lines. First there is an ordering data-entry program that checks the entered company code with a relational master data table. Then someone else processes the ordering data and yet another program sends the result to the company mentioned earlier, based on the address in the master data table. > > Nothing exciting, so what do you think? Of course there is a program to maintain the master data, which introduces the posibility that sending fails: enter ordering data, delete the company and try to send the ordering data. > > (Please hang on for another minute, I am getting to FP.) > > First of all, the initial development budget is tight, so this is just how it is being programmed. The failure will simply be dumped on an operator. In a second version someone programs that a company cannot be deleted if there are outstanding orders. Then someone realizes the burden on the operator and the possible starvation: if enough orders are being entered, the company can never be deleted. Therefore a boolean is added to each company record. If the system manager wants to delete a company, s/he sets the boolean to False and the company will no longer be allowed when entering ordering data. Periodically a batch program removes the company records with the boolean set to False, which have no outstanding orders. > > Things like these happen a thousand times, while it is nothing more than a garbage collection problem. A thousand times operators, analysts and programmers are loaded with work to overcome it. Also system documentation covers the particular garbage collection solution, which is essentially non-information. > > Now while FP's have adequately solved this garbage collection problem for single executables and their RAM-heap, I am not aware of any practical solution that also garbage collects database records or files. > > Does anybody know about work in this direction? > > Regards Erik Zuurbier From aondi@fit.edu Wed, 26 Nov 2003 13:07:20 -0500 Date: Wed, 26 Nov 2003 13:07:20 -0500 From: Attila Ondi aondi@fit.edu Subject: [clean-list] questions -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hi all, Thanks for pointing out parser combinators. I even found a paper (actually a chapter of a (still written?) book) at the Clean website (http://www.cs.kun.nl/~clean/download/papers/cleanbook/II.05.ParserCombinators.pdf) just about parser combinators. It was very useful and helped a lot in solving my problem more nicely. This leaves open only my second question: Is there any data structure library for Clean? One that contains data structures (and functions for handling them), like HashTable, Set and so on? Thank you for the help, Attila fzuurbie@inter.nl.net wrote: |>There's nothing better than regexps for string handling | | | Until you found out about combinator parsing (type this in in Google or CiteSeer). I have a library based on Koopman's and Rojemo's work (continuation passing style), extended with elaborated error messages. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.0.7 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iQCVAwUBP8Tr2B5adN4t/v+OAQIplQQAhip1dBaM1j0UNsOq5gYSdjqlbBwkK3kp IA9+TqvGNkke7KXud2YQh0mHyiAkCcCIc6enjKy1KRa0vKHIZTRhbIMeW7Efl6U7 alPfeb+4TFk8DZ+V3U4sW6kJDhk/Rs0rM8JVZYpvsSazCn1PLGVWfhDmZG6Y8x5S Kt6rTDUS7Qk= =69ME -----END PGP SIGNATURE----- From m.wittebrood@mailbox.kun.nl Sat, 29 Nov 2003 00:08:41 +0100 Date: Sat, 29 Nov 2003 00:08:41 +0100 From: Marco Kesseler m.wittebrood@mailbox.kun.nl Subject: [clean-list] Linux PowerPC Version Hi, FYI, I have built (bootstrapped) a PowerPC version of Clean 2.1 for Linux. I will try to get this online somewhere. In the meantime, if people are interested, I can mail a gzipped archive with binaries and the changed sources (almost 2MB). The core functionality works: I have compiled the compiler itself as a test, but some more advanced things will not work. Some things won't because they are not supported on Linux, others because I had other priorities. The archive contains some readme's with additional information. While hunting down problems in the runtime system, and learning a bit about PowerPC assembly, I documented part of the garbage collector sources. So if people are interested in a glimpse of the internal node structures in Clean, they might want to have a look at that (it's not complete though, and probably still quite hard to follow). have fun, Marco From karczma@info.unicaen.fr Mon, 01 Dec 2003 09:48:52 +0100 Date: Mon, 01 Dec 2003 09:48:52 +0100 From: Jerzy Karczmarczuk karczma@info.unicaen.fr Subject: [clean-list] Strict lists kill me... Gentle gurus. I wrote a short program which generates co-recursively a stream representing the sampled sine function, using the identity: sin(x+2h) = 2 sin(x+h)*cos(h) - sin(x) Of course, the algorithm shown below being co-recursive needs spine laziness. But I don't need - I think... - to have the head laziness. So, I wrote three identical versions using [], [!] and [#]. Here it is: // ============================================= module litest import StdEnv, StdStrictLists, StdOverloadedList class (*>) infixr 7 t :: !Real (t Real) -> (t Real) instance *> [] where (*>) x l = map (\s -> x*s) l instance *> [!] where (*>) x l = Map (\s -> x*s) l instance *> [#] where (*>) x l = Map (\s -> x*s) l ZipWith op [|a:as] [|b:bs] = [|(op a b) : ZipWith op as bs] ZipWith op as bs = [|] instance - [#Real] where (-) l1 l2 = ZipWith (-) l1 l2 instance - [!Real] where (-) l1 l2 = ZipWith (-) l1 l2 instance - [Real] where (-) l1 l2 = ZipWith (-) l1 l2 oscilu =: (z,v,r) where z =: [# 0.0 : v] v =: [# sin 0.01 : r] r =: (2.0*cos 0.01)*>v - z oscils =: (z,v,r) where z =: [! 0.0 : v] v =: [! sin 0.01 : r] r =: (2.0*cos 0.01)*>v - z oscill =: (z,v,r) where z =: [0.0 : v] v =: [sin 0.01 : r] r =: (2.0*cos 0.01)*>v - z Start = let (a,b,c) = oscill in (Take 10 a, Take 10 b, Take 10 c) // ==================================================== The operator (*>) multiplies a list by a scalar. It, and the 2-mapped (-) are duly overloaded. The result is the list, its tail, and its tail_tail. Yes, it seems silly, first element should suffice. But now comes the issue. The program - as it is - produces the expected result. Change oscill into oscils in Start. Ready to guess the result? Here it is: ([],[.0099998333416666],[]) Nice, isn't it, especially the tail of the empty list... ============================================================================ Now, change oscils into oscilu. Ready for another guess? (Run Time Warning: cycle in spine detected *************************************************************************** This is all. I suspect that this might be a bug somewhere in the treatment of not-entirely-lazy lists. Perhaps the translation between (:) and cons, cons_u or whatever is imperfect. Perhaps the overloading plays some dirty tricks. Or, perhaps I simply I did something illegal in my coding, in this case I would very humbly suggest to introduce some appropriate caveats into the documentation... Thank you. Jerzy Karczmarczuk Caen, France From karczma@info.unicaen.fr Mon, 01 Dec 2003 14:01:29 +0100 Date: Mon, 01 Dec 2003 14:01:29 +0100 From: Jerzy Karczmarczuk karczma@info.unicaen.fr Subject: [clean-list] Re: Strict lists kill me... More on it... Reminder: I sent a triple-version program which generates a co-recursive stream - a sampled sinusoid. This needed lazy lists. With normal lists it works, with head-strict [!Real] lists it produces rubbish, with unboxed [#Real] it finds a spine black-hole... So I tested another example. prefx :: [#Real] prefx =: ... some filling, e.g. random numbers. No problemo Baby strm =: prefx ++| z where z = 0.5 *> (strm + Tl strm) This time it works without complaining. So, scratching my head I replaced oscilu =: (z,v,r) where z =: [# 0.0 : v] v =: [# sin 0.01 : r] r =: (2.0*cos 0.01)*>v - z which generated the spine loop error message, by: oscilu =: (z,v,r) where z =: [# 0.0] ++| v v =: [# sin 0.01] ++| r r =: (2.0*cos 0.01)*>v - z i.e., I did thing which I tell my students *never to do*. And miracle happened, it works. So, it seems that the pattern [# x : l] does something awful. But what, and who is to blame? Thanks. Jerzy Karczmarczuk From johnvg@cs.kun.nl Mon, 1 Dec 2003 16:19:22 +0100 Date: Mon, 1 Dec 2003 16:19:22 +0100 From: John van Groningen johnvg@cs.kun.nl Subject: [clean-list] Re: Strict lists kill me... Jerzy Karczmarczuk writes: >More on it... > >Reminder: I sent a triple-version program which generates >a co-recursive stream - a sampled sinusoid. This needed >lazy lists. With normal lists it works, with head-strict >[!Real] lists it produces rubbish, with unboxed [#Real] >it finds a spine black-hole... The compiler generates incorrect code for a strict or unboxed list constructor on a cycle that is in a strict context or in a lazy context with an already evaluated head (or tail for tail strict lists). In this case > z =: [# 0.0 : v] in function oscils or oscilu. In the case of a strict (boxed) list an incorrect label is generated for the constructor, which causes pattern matching on the constructor to fail. For an unboxed list an incorrect stack offset is generated for the tail of the constructor. An improved backend.dll for windows is available at: http://www.cs.kun.nl/~clean/download/Clean21/windows/backend.zip This dll is stored in the directory Tools/Clean System 2.1.0. Or replace lines 3077-3079 in codegen2.c with: GenFillR (strict_cons_lab_p,a_size,b_size,*asp_p-update_node_id->nid_a_index,0,0,node->node_state.state_kind==SemiStrict ? ReleaseAndFill : NormalFill,True); else GenFillh (node->node_arity==2 ? &cons_lab : strict_cons_lab_p,a_size,*asp_p-update_node_id->nid_a_index,node->node_state.state_kind==SemiStrict ? ReleaseAndFill : NormalFill); and recompile the compiler, backend.dll or CleanCompilerLib, depending on the platform. >So I tested another example. > >prefx :: [#Real] >prefx =: ... some filling, e.g. random numbers. No problemo Baby > >strm =: prefx ++| z > where z = 0.5 *> (strm + Tl strm) > >This time it works without complaining. So, scratching my head >I replaced Yes, because there is no contructor on a cycle. >oscilu =: (z,v,r) where > z =: [# 0.0 : v] > v =: [# sin 0.01 : r] > r =: (2.0*cos 0.01)*>v - z > >which generated the spine loop error message, by: > >oscilu =: (z,v,r) where > z =: [# 0.0] ++| v > v =: [# sin 0.01] ++| r > r =: (2.0*cos 0.01)*>v - z > >i.e., I did thing which I tell my students *never to do*. >And miracle happened, it works. This works because [# 0.0] is no longer on a cycle. >So, it seems that the pattern [# x : l] does something awful. >But what, and who is to blame? See my explanation above. By the way, the oscil functions are now CAFs because you use =:, this will probably introduce a space leak. And for better performance you may want to define ZipWith as a macro: ZipWith op l1 l2 :== ZipWith l1 l2 where ZipWith [|a:as] [|b:bs] = [|(op a b) : ZipWith as bs] ZipWith as bs = [|] Or instead enable fusion by passing :: -fusion as a compiler flag. Regards, John van Groningen From brent.fulgham@xpsystems.com Mon, 1 Dec 2003 17:16:40 -0800 Date: Mon, 1 Dec 2003 17:16:40 -0800 From: Brent Fulgham brent.fulgham@xpsystems.com Subject: [clean-list] Linux PowerPC Version I would be interested in any makefile or source changes you needed to do this so I can update the Debian packages to build a PowerPC version. Thanks, -Brent > -----Original Message----- > From: clean-list-admin@cs.kun.nl [mailto:clean-list-admin@cs.kun.nl]On > Behalf Of Marco Kesseler > Sent: Friday, November 28, 2003 3:09 PM > To: clean-list@cs.kun.nl > Subject: [clean-list] Linux PowerPC Version > > > Hi, > > FYI, I have built (bootstrapped) a PowerPC version of Clean 2.1 for > Linux. I will try to get this online somewhere. In the meantime, if > people are interested, I can mail a gzipped archive with binaries and > the changed sources (almost 2MB). > > The core functionality works: I have compiled the compiler itself as a > test, but some more advanced things will not work. Some things won't > because they are not supported on Linux, others because I had other > priorities. The archive contains some readme's with additional > information. > > While hunting down problems in the runtime system, and learning a bit > about PowerPC assembly, I documented part of the garbage collector > sources. So if people are interested in a glimpse of the internal node > structures in Clean, they might want to have a look at that (it's not > complete though, and probably still quite hard to follow). > > have fun, > Marco > > > > > _______________________________________________ > clean-list mailing list > clean-list@cs.kun.nl > http://www.cs.kun.nl/mailman/listinfo/clean-list > From karczma@info.unicaen.fr Tue, 02 Dec 2003 12:07:25 +0100 Date: Tue, 02 Dec 2003 12:07:25 +0100 From: Jerzy Karczmarczuk karczma@info.unicaen.fr Subject: [clean-list] Re: Strict lists kill me... John van Groningen wrote: > The compiler generates incorrect code for a strict or unboxed > list constructor on a cycle that is in a strict context or > in a lazy context with an already evaluated head (or tail for > tail strict lists). ... > An improved backend.dll for windows is available [...] Thank you very much John for so prompt reaction. I knew I can count on you, but less than 24 hours to correct a compiler bug? And thank you for your comments concerning the efficiency of all these (=:) and (:==) intricacies. Clean is full of black magic. Perhaps one day some specific categories of advice, notably about the Essence of Laziness/ Strictness might be better documented? I have one case which I don't *really* understand, although I understand it superficially, and there is nothing wrong with it. My bombed examples -- the sampled sinusoid and the other lazy stream, which implements co-recursively the Karplus-Strong algorithm -- are *sound* samples. Converted to *{#Char} and played as .wav buffers. You may imagine that in the case of sound the synchro- asynchro- issues are quite important. But sometimes the graph-reduction has its own ideas about the order of events. Look at the [fragment of the] following program: // ======================== Start :: *World -> (*World,*File) Start wrld # (console,wrld) = stdio wrld # console = fwrites "beginning of first fragment\n" console # (a,wrld) = playWav "file1.wav" wrld # console = fwrites "end of first fragment\n" console # (b,wrld) = playWav "file2.wav" wrld # console = fwrites "end of second fragment\n" console = (wrld,console) // ======================== Its execution begins by writing: ( Then *both* files are played, and finally the console displays at once: 65536,beginning of the first fragment end of first fragment end of second fragment (File -1 4254404) ////////////////////////////////////////////////////////////////////// Hmmm. I thought then that forcing the strictness of the sharp-let will serialize the actions appropriately. It does serialize them, but in a way I *didn't* expect. Replace all # by #! The result is: first, the console writes the text: beginning of the first fragment end of first fragment end of second fragment ... and then plays both files. And finishes by writing (65536,File -1 4250308) I imagine that demanding the interaction and forcing the reading of something will - perhaps - change this order, but without that, what would be your recommended way to serialize (monadify??) the actions above in an intuitive (obvious) order? *** My superficial understanding is that the lines which use console are chained independently of instructions which handle wrld, so there is - a priori - no intrinsic, explicitly visible relative order among them. So I replaced everywhere console = XXX console by (console,wrld) = (XXX console,wrld) but it didn't help. Perhaps it has been simply optimized away. Perhaps the idea is too silly [which I suspect]. Thank you. And I promise more... Jerzy Karczmarczuk From fzuurbie@inter.nl.net Tue, 2 Dec 2003 11:52:54 UT Date: Tue, 2 Dec 2003 11:52:54 UT From: fzuurbie@inter.nl.net fzuurbie@inter.nl.net Subject: [clean-list] Re: Strict lists kill me... This is a multi-part message in MIME format. --_----------=_1070365974239561 Content-Disposition: inline Content-Length: 270 Content-Transfer-Encoding: binary Content-Type: text/plain I also have a problem understanding the difference between # and #!. Sometimes I have a space leak that goes away when I change some # to #! or back. Sometimes a #! cures a uniqueness error. But I never really understood the semantics of #!. Regards Erik Zuurbier --_----------=_1070365974239561-- From peter88@cs.kun.nl Tue, 02 Dec 2003 13:41:33 +0100 Date: Tue, 02 Dec 2003 13:41:33 +0100 From: Peter Achten peter88@cs.kun.nl Subject: [clean-list] Re: Strict lists kill me... At 12:07 2-12-03 +0100, Jerzy Karczmarczuk wrote: >[..]You may imagine that in the case of sound the synchro- asynchro- >issues are quite important. But sometimes the graph-reduction >has its own ideas about the order of events. Look at the >[fragment of the] following program: > >// ======================== >Start :: *World -> (*World,*File) >Start wrld > # (console,wrld) = stdio wrld > # console = fwrites "beginning of first fragment\n" console > # (a,wrld) = playWav "file1.wav" wrld > # console = fwrites "end of first fragment\n" console > # (b,wrld) = playWav "file2.wav" wrld > # console = fwrites "end of second fragment\n" console > = (wrld,console) >// ======================== >[..] The point is, as you state: >My superficial understanding is that the lines which use console are chained >independently of instructions which handle wrld, so there is - a priori - no >intrinsic, explicitly visible relative order among them. You have specified no relation between console and world; therefore any sequential interleaving order of console operations and world operations is a valid execution of this program. Strictness is of no help; what you need is data-dependency between console and world, for instance by closing the console immediately after writing to it. This will relate console and world. Then you obtain the following code: Start wrld # wrld = toConsole "beginning of first fragment\n" wrld # (a,wrld) = playWav "file1.wav" wrld # wrld = toConsole "end of first fragment\n" wrld # (b,wrld) = playWav "file2.wav" wrld # wrld = toConsole "end of second fragment\n" wrld = wrld toConsole :: String *World -> *World toConsole str world = let (console,world`) = stdio world in snd (fclose (console <<< str) world`) Regards, Peter From brent.fulgham@xpsystems.com Tue, 2 Dec 2003 11:49:21 -0800 Date: Tue, 2 Dec 2003 11:49:21 -0800 From: Brent Fulgham brent.fulgham@xpsystems.com Subject: [clean-list] Linux PowerPC Version > P.S. Yes, the wish list is becoming slightly outdated, so I > will try to maintain it a bit in the coming weeks or so. > There have been a few updates in the past several weeks related to bugs identified in the field and fixed in the Windows version. Linux fixes were reported to be forthcoming in the next release. Do you know when the next release might be? If it will be another 6 - 8 months, perhaps providing snapshots with the fixes would be useful for users. Thanks, -Brent From m.wittebrood@mailbox.kun.nl Tue, 02 Dec 2003 20:45:14 +0100 Date: Tue, 02 Dec 2003 20:45:14 +0100 From: Marco Kesseler m.wittebrood@mailbox.kun.nl Subject: [clean-list] Linux PowerPC Version Hi, I have added a link at the Clean wish list: http://www.cs.kun.nl/~clean/wish/Clean21PPC.tar.gz regards, Marco Kesseler P.S. Yes, the wish list is becoming slightly outdated, so I will try to maintain it a bit in the coming weeks or so. -----Original Message----- From: clean-list-admin@cs.kun.nl [mailto:clean-list-admin@cs.kun.nl] On Behalf Of Brent Fulgham Sent: dinsdag 2 december 2003 2:17 To: Marco Kesseler; clean-list@cs.kun.nl Subject: RE: [clean-list] Linux PowerPC Version I would be interested in any makefile or source changes you needed to do this so I can update the Debian packages to build a PowerPC version. Thanks, -Brent > -----Original Message----- > From: clean-list-admin@cs.kun.nl [mailto:clean-list-admin@cs.kun.nl]On > Behalf Of Marco Kesseler > Sent: Friday, November 28, 2003 3:09 PM > To: clean-list@cs.kun.nl > Subject: [clean-list] Linux PowerPC Version > > > Hi, > > FYI, I have built (bootstrapped) a PowerPC version of Clean 2.1 for > Linux. I will try to get this online somewhere. In the meantime, if > people are interested, I can mail a gzipped archive with binaries and > the changed sources (almost 2MB). > > The core functionality works: I have compiled the compiler itself as a > test, but some more advanced things will not work. Some things won't > because they are not supported on Linux, others because I had other > priorities. The archive contains some readme's with additional > information. > > While hunting down problems in the runtime system, and learning a bit > about PowerPC assembly, I documented part of the garbage collector > sources. So if people are interested in a glimpse of the internal node > structures in Clean, they might want to have a look at that (it's not > complete though, and probably still quite hard to follow). > > have fun, > Marco > > > > > _______________________________________________ > clean-list mailing list > clean-list@cs.kun.nl > http://www.cs.kun.nl/mailman/listinfo/clean-list > _______________________________________________ clean-list mailing list clean-list@cs.kun.nl http://www.cs.kun.nl/mailman/listinfo/clean-list From m.wittebrood@mailbox.kun.nl Tue, 02 Dec 2003 21:45:12 +0100 Date: Tue, 02 Dec 2003 21:45:12 +0100 From: Marco Kesseler m.wittebrood@mailbox.kun.nl Subject: [clean-list] Linux PowerPC Version Sorry, I don't know. Yes, such snapshots would be VERY useful. "perhaps" is an understatement. I for one, would not mind building the PowerPC stuff on a regular basis, provided I can get hold of the latest sources. Marco -----Original Message----- From: Brent Fulgham [mailto:brent.fulgham@xpsystems.com] Sent: dinsdag 2 december 2003 20:49 To: Marco Kesseler; clean-list@cs.kun.nl Subject: RE: [clean-list] Linux PowerPC Version > P.S. Yes, the wish list is becoming slightly outdated, so I > will try to maintain it a bit in the coming weeks or so. > There have been a few updates in the past several weeks related to bugs identified in the field and fixed in the Windows version. Linux fixes were reported to be forthcoming in the next release. Do you know when the next release might be? If it will be another 6 - 8 months, perhaps providing snapshots with the fixes would be useful for users. Thanks, -Brent From karczma@info.unicaen.fr Wed, 03 Dec 2003 09:26:48 +0100 Date: Wed, 03 Dec 2003 09:26:48 +0100 From: Jerzy Karczmarczuk karczma@info.unicaen.fr Subject: [clean-list] Re: Strict lists kill me... Peter Achten answers my query about the non-interleaving of playing and writing in: >> # console = fwrites "beginning of first fragment\n" console >> # (a,wrld) = playWav "file1.wav" wrld >> # console = fwrites "end of first fragment\n" console >> # (b,wrld) = playWav "file2.wav" wrld >> # console = fwrites "end of second fragment\n" consol > You have specified no relation between console and world; therefore any > sequential interleaving order of console operations and world operations > is a valid execution of this program. Strictness is of no help; what you > need is data-dependency between console and world, for instance by > closing the console immediately after writing to it. ... Thank you, indeed. But - as I explicitly said - I know that. I confessed that I had some superficial understanding of the reasons why it *might* play everything and then write everything, although I don't find it natural, since the event synchronisation *might* be coherent even without data dependencies. I decided to send my posting when I discovered that it is not entirely true that strictless is meaningless here. After having replaced # by #! all console output was generated *BEFORE* the sound playing. So, there are some dark corners within the compiler soul... But OK, I will look up how the interactive games are structured. Thanks again. Jerzy Karczmarczuk From ronny@cs.kun.nl Wed, 03 Dec 2003 10:39:45 +0100 Date: Wed, 03 Dec 2003 10:39:45 +0100 From: Ronny Wichers Schreur ronny@cs.kun.nl Subject: [clean-list] Linux PowerPC Version Marco Kesseler writes (to the Clean discussion list): >I for one, would not mind building the PowerPC stuff on a regular basis, >provided I can get hold of the latest sources. > Our public read-only CVS (updated every hour) :pserver:anonymous@cvs-srv.cs.kun.nl/clean Web-access: Cheers, Ronny Wichers Schreur From johnvg@cs.kun.nl Thu, 4 Dec 2003 17:07:20 +0100 Date: Thu, 4 Dec 2003 17:07:20 +0100 From: John van Groningen johnvg@cs.kun.nl Subject: [clean-list] Re: Strict lists kill me... Jerzy Karczmarczuk wrote: >... >I have one case which I don't *really* understand, although >I understand it superficially, and there is nothing wrong with >it. My bombed examples -- the sampled sinusoid and the other >lazy stream, which implements co-recursively the Karplus-Strong >algorithm -- are *sound* samples. Converted to *{#Char} and >played as .wav buffers. > >You may imagine that in the case of sound the synchro- asynchro- >issues are quite important. But sometimes the graph-reduction >has its own ideas about the order of events. Look at the >[fragment of the] following program: > >// ======================== >Start :: *World -> (*World,*File) >Start wrld > # (console,wrld) = stdio wrld > # console = fwrites "beginning of first fragment\n" console > # (a,wrld) = playWav "file1.wav" wrld > # console = fwrites "end of first fragment\n" console > # (b,wrld) = playWav "file2.wav" wrld > # console = fwrites "end of second fragment\n" console > = (wrld,console) >// ======================== > >Its execution begins by writing: >( > >Then *both* files are played, >and finally the console displays at once: > > 65536,beginning of the first fragment >end of first fragment >end of second fragment >(File -1 4254404) > >////////////////////////////////////////////////////////////////////// > >Hmmm. I thought then that forcing the strictness of the sharp-let will >serialize the actions appropriately. It does serialize them, but in >a way I *didn't* expect. > >Replace all # by #! > >The result is: first, the console writes the text: > >beginning of the first fragment >end of first fragment >end of second fragment > >... and then plays both files. And finishes by writing (65536,File -1 4250308) #! does not serialize the evaluation of the expressions, but forces the evaluation of those expressions before or during the evaluation of the root expression, or if #! is used before a guard, before or during the evaluation of the guard. The compiler does not use the order of the definitions between '#!' and '=' or '|' to determine the order of evaluation. Only the expression at the right of the '=' is evaluated, not the variables in the pattern before the '='. However, if the result of an expression in a #! is used by another expression in a #!, the first expression will always be evaluated before the latter, even if the arguments of the second expression that use the result of the first expression are not strict. If the result of an expression in a #! is never used, the compiler will remove this expression and give a warning. The compiler will not move expressions inside an alternative of a guard, even if the result is used only if the guard succeeds (or fails). In that case the expression in the #! will be evaluated before or during the evaluation of the guard. >I imagine that demanding the interaction and forcing the reading of something >will - perhaps - change this order, but without that, what would be your >recommended way to serialize (monadify??) the actions above in an intuitive >(obvious) order? If you want to evaluate a function f before a function g, make sure that one of the argument of f uses the result of g, and make one of those arguments strict. If there is no such argument, you can add a dummy argument. In this case make 'playWav' strict in the second argument (wrld), add a 'fwrites' function with an extra strict wrld argument, and because wrld is unique, return the wrld as well. Finally make the result of this function strict in the tuple element that contains the file, to force the evaluation of 'fwrites' when this function is called. Otherwise it would only create a closure for fwrites, because tuples are lazy. So: fwrites2 :: {#Char} *File !*World -> (!*File,*World) fwrites2 s file console = (fwrites s file,console); Start wrld # (console,wrld) = stdio wrld # (console,wrld) = fwrites2 "beginning of first fragment\n" console wrld # (a,wrld) = playWav "file1.wav" wrld # (console,wrld) = fwrites2 "end of first fragment\n" console wrld # (b,wrld) = playWav "file2.wav" wrld # (console,wrld) = fwrites2 "end of second fragment\n" console wrld = (wrld,console) Another possibility is to add a function that synchronises both actions, with strictness annotations for all arguments and results. In this case, make 'playWav' strict in the second argument (wrld) again, and add a 'sync_console' function with strict arguments and results: sync_console :: !*File !*World -> (!*File,!*World) sync_console console world = (console,world) Start wrld # (console,wrld) = stdio wrld # console = fwrites "beginning of first fragment\n" console # (console,wrld) = sync_console console wrld # (a,wrld) = playWav "file1.wav" wrld # (console,wrld) = sync_console console wrld # console = fwrites "end of first fragment\n" console # (console,wrld) = sync_console console wrld # (b,wrld) = playWav "file2.wav" wrld # (console,wrld) = sync_console console wrld # console = fwrites "end of second fragment\n" console # (console,wrld) = sync_console console wrld = (wrld,console) Or use a lazy synchronise function, without strictness annotations in the function types, and without making 'playWav' strict in the wrld argument, but with a #! : lazy_sync_console console world = (console,world) Start wrld #! (console,wrld) = stdio wrld console = fwrites "beginning of first fragment\n" console (console,wrld) = lazy_sync_console console wrld (a,wrld) = playWav "file1.wav" wrld (console,wrld) = lazy_sync_console console wrld console = fwrites "end of first fragment\n" console (console,wrld) = lazy_sync_console console wrld (b,wrld) = playWav "file2.wav" wrld (console,wrld) = lazy_sync_console console wrld console = fwrites "end of second fragment\n" console (console,wrld) = lazy_sync_console console wrld = (wrld,console) Yet another way to force a specific order of evaluation is by using guards, because the compiler does not change the order in which guards are evaluated. In this case we need some eval functions that evaluate an argument using a strictness annotation and return False or True. For example: eval_console :: !File -> Bool eval_console console = False eval_world :: !World -> Bool eval_world world = False Start wrld # (console,wrld) = stdio wrld # console = fwrites "beginning of first fragment\n" console | eval_console console = undef # (a,wrld) = playWav "file1.wav" wrld | eval_world wrld = undef # console = fwrites "end of first fragment\n" console | eval_console console = undef # (b,wrld) = playWav "file2.wav" wrld | eval_world wrld = undef # console = fwrites "end of second fragment\n" console | eval_console console = undef = (wrld,console) Or use the fact that expressions in #! are not moved inside guarded alternatives: Start wrld #! (console,wrld) = stdio wrld #! console = fwrites "beginning of first fragment\n" console | False = undef #!(a,wrld) = playWav "file1.wav" wrld | False = undef #!console = fwrites "end of first fragment\n" console | False = undef #!(b,wrld) = playWav "file2.wav" wrld | False = undef #!console = fwrites "end of second fragment\n" console | False = undef = (wrld,console) >*** > >My superficial understanding is that the lines which use console are chained >independently of instructions which handle wrld, so there is - a priori - no >intrinsic, explicitly visible relative order among them. >So I replaced everywhere > >console = XXX console > >by > >(console,wrld) = (XXX console,wrld) > >but it didn't help. Perhaps it has been simply optimized away. Perhaps the idea >is too silly [which I suspect]. You probably did not make the first argument of the tuple strict to evaluate 'XXX console'. Instead a closure is created that is evaluated later. Regards, John van Groningen From billwood42@comcast.net Thu, 4 Dec 2003 22:34:20 -0700 Date: Thu, 4 Dec 2003 22:34:20 -0700 From: Bill Wood billwood42@comcast.net Subject: [clean-list] Clean in the Real World I have a question about Clean -- Is it ready for prime time? More specifically: 1) Has Clean been used successfully for large, deployed, production-grade applications? 2) How difficult is it to get a programming group experienced in, say, C, Pascal and Assembler to get up-to-speed with Clean? -- How expensive in training and ramp-up time? 3) How does Clean code compare in speed and memory use with imperative languages? 4) How great is the "distance" between Clean code designed for clarity and Clean code designed for performance? -- "academic" versus "real" code? 5) How severe is the overhead for the Foreign Function Interface (e.g., htoclean)? 6) Would anyone recommend using Clean to handle complex logic involving access to a multi-gigabyte database, in a transaction processing environment? I like the idea of using an FP language for my application -- I think it has many of the characteristics usually touted of OOP, and I think the functional model is simpler and more robust. But if I'm going to sell the idea to management, I need a really good, defensible story. I appreciate any insight anyone can provide. If you don't want to consume bandwidth, reply directly to me. Many thanks, -- Bill Wood bill.wood@acm.org From fzuurbie@inter.nl.net Fri, 5 Dec 2003 09:25:50 UT Date: Fri, 5 Dec 2003 09:25:50 UT From: fzuurbie@inter.nl.net fzuurbie@inter.nl.net Subject: [clean-list] Clean in the Real World This is a multi-part message in MIME format. --_----------=_1070616350187172 Content-Disposition: inline Content-Length: 1741 Content-Transfer-Encoding: binary Content-Type: text/plain Bill, > 1) Has Clean been used successfully for large, deployed, production- > grade > applications? The Clean compiler, the Clean IDE, the Sparkle proof tool. Clean lacks exception handling though. If (a part of) an application runs out of stack or heap space, the application just quits. If you want to tell the user that a certain action cannot be completed because of a memory restriction, you have to detarmine the memory needs in advance (if you can) and explicitly program a test on that. > > 2) How difficult is it to get a programming group experienced in, say, > C, > Pascal and Assembler to get up-to-speed with Clean? > -- How expensive in training and ramp-up time? > The experience is probably counter-productive. > 3) How does Clean code compare in speed and memory use with imperative > languages? Clean is supposed to be nearly as fast, but of course, see 4) below > > 4) How great is the "distance" between Clean code designed for clarity > and > Clean code designed for performance? > -- "academic" versus "real" code? The compiler - written in Clean - was optimized for speed. Probably a number of higher order functions and other aspects that would further clarity have been hand-optimized away. The good news is that with the recent fusion algorithm a number of those hand-optimizations have been automated, so that code clarity can be retained fo future applications. > 6) Would anyone recommend using Clean to handle complex logic involving > access > to a multi-gigabyte database, in a transaction processing > environment? > Noone probably. I haven't heard about any interface from Clean to any database system. Regards Erik Zuurbier --_----------=_1070616350187172-- From m.wittebrood@mailbox.kun.nl Fri, 05 Dec 2003 23:51:02 +0100 Date: Fri, 05 Dec 2003 23:51:02 +0100 From: Marco Kesseler m.wittebrood@mailbox.kun.nl Subject: [clean-list] Clean in the Real World On Fri, 2003-12-05 at 10:25, fzuurbie@inter.nl.net wrote: > Bill, > > > 1) Has Clean been used successfully for large, deployed, production- > > grade > > applications? > > The Clean compiler, the Clean IDE, the Sparkle proof tool. Clean lacks > exception handling though. If (a part of) an application runs out of > stack or heap space, the application just quits. If you want to tell > the user that a certain action cannot be completed because of a memory > restriction, you have to detarmine the memory needs in advance (if you > can) and explicitly program a test on that. I do agree that dealing with memory requirements can be difficult in a lazy functional language, but I am not sure what kind of handling you have in mind when a program REALLY runs out of memory. I know of plenty commercial software that "just quits" in those circumstances. Now on systems with a lot of virtual memory it may take a while before you reach that situation, but then it REALLY takes a while, because your system starts trashing. As to convincing management to use Clean: this has usually nothing to do with technical issues. Try to convince them not to do what everybody else does, and not to blame you personally when it fails. regards, Marco From xset@mail.ru Sat, 6 Dec 2003 14:26:54 +0600 Date: Sat, 6 Dec 2003 14:26:54 +0600 From: XSet xset@mail.ru Subject: [clean-list] How to compile Clean in Windows? This is a multi-part message in MIME format. ------=_NextPart_000_002F_01C3BC04.FF087020 Content-Type: text/plain; charset="koi8-r" Content-Transfer-Encoding: quoted-printable I saw sources and found CodeForge project files. But I have not = CodeForge IDE. What compiler are used to make windows version of Clean ? = Can I compile it with MSVC 6.0 ? Thanks in advance. ------=_NextPart_000_002F_01C3BC04.FF087020 Content-Type: text/html; charset="koi8-r" Content-Transfer-Encoding: quoted-printable
I saw sources and found CodeForge = project=20 files. But I have not CodeForge IDE. What compiler are used to make = windows=20 version of Clean ? Can I compile it with MSVC 6.0 ?
 
Thanks in = advance.
------=_NextPart_000_002F_01C3BC04.FF087020-- From karczma@info.unicaen.fr Mon, 08 Dec 2003 19:03:11 +0100 Date: Mon, 08 Dec 2003 19:03:11 +0100 From: Jerzy Karczmarczuk karczma@info.unicaen.fr Subject: [clean-list] Strict lists strike again... Illustrissimi Condottieri: A silly, wasteful infinite repetition for unboxed stuff, say Reals: rep :: !Real -> [#Real] rep x = [x : rep x] works. But making it just a cycle: Rep x = z where z = [# x : z] as the obverloaded Repeat does - - chokes and dies, yelling horribly. (Clean 2.1, Microsoft Windows), after having displayed on the console some small number, close to floating underflow. The system wants even to launch the debugger, so there is some access violation somewhere in the generated code. Best regards Jerzy Karczmarczuk From greenrd@greenrd.org Mon, 8 Dec 2003 20:52:58 +0000 Date: Mon, 8 Dec 2003 20:52:58 +0000 From: Robin Green greenrd@greenrd.org Subject: [clean-list] Clean in the Real World On Fri, Dec 05, 2003 at 11:51:02PM +0100, Marco Kesseler wrote: > As to convincing management to use Clean: this has usually nothing to do > with technical issues. Try to convince them not to do what everybody > else does, and not to blame you personally when it fails. Interesting choice of words! WHEN not IF, eh? ;-) -- Robin From m.wittebrood@mailbox.kun.nl Tue, 09 Dec 2003 00:01:40 +0100 Date: Tue, 09 Dec 2003 00:01:40 +0100 From: Marco Kesseler m.wittebrood@mailbox.kun.nl Subject: [clean-list] Clean in the Real World >On Fri, Dec 05, 2003 at 11:51:02PM +0100, Marco Kesseler wrote: >> As to convincing management to use Clean: this has usually nothing to do >> with technical issues. Try to convince them not to do what everybody >> else does, and not to blame you personally when it fails. > >Interesting choice of words! WHEN not IF, eh? ;-) What can I say: * I sometimes make english writing mistakes... * how quick is management on deciding that a project "has failed", and how many serious projects do you know that never reached a point that things weren't going all that well. Failure does not have to be a technical thing either. So it should have been "if", but "when" may not be too far off. I'd not try Clean for the main course just yet, but as an appetizer it may be nice. Marco From brent.fulgham@xpsystems.com Mon, 8 Dec 2003 15:19:30 -0800 Date: Mon, 8 Dec 2003 15:19:30 -0800 From: Brent Fulgham brent.fulgham@xpsystems.com Subject: [clean-list] Clean in the Real World > Clean lacks exception handling though. If (a part of) an > application runs out of stack or heap space, the application > just quits. This makes some sense, since Exceptions (by their nature) are not functional. However, from a pragmatic standpoint I wonder if their lack may make writing robust software in Clean more difficult. Does Clean provide something like the exception model proposed in Simon Peyton-Jones et. al "A Semantics for Imprecise Exceptions" (http://research.microsoft.com/Users/simonpj/Papers/imprecise-exn.htm)? What is the recommended approach for dealing with exceptional/error conditions in Clean? -Brent From greenrd@greenrd.org Tue, 9 Dec 2003 01:34:19 +0000 Date: Tue, 9 Dec 2003 01:34:19 +0000 From: Robin Green greenrd@greenrd.org Subject: [clean-list] Clean in the Real World On Mon, Dec 08, 2003 at 03:19:30PM -0800, Brent Fulgham wrote: > > Clean lacks exception handling though. If (a part of) an > > application runs out of stack or heap space, the application > > just quits. > > This makes some sense, since Exceptions (by their nature) are not functional. Well, that's arguable. You can in principle do exceptions as values, e.g. have everything return a type which contains a value and a flag to indicate whether the value is to be treated as an exception. But that changes the semantics of your program (and how you write it). It's not that it can't be done in a functional way, it's that it's a highly questionable way to do it - for performance and genericity reasons, for example. In terms of performance, you'd have all these checks going on all the time every time you compute anything at all. In terms of genericity, you could either make only some functions support exceptions (which would limit their reusability) or make all functions support exceptions - which would motivate moving exception machinery into the language itself, rather than redundantly putting it everywhere. And then are you going to lose a little bit of purity? Well, yes - but in translating a program into exceptions-as-value style you in general lose a little bit of purity anyway, namely opacity of order of evaluation. Given that in the real world, "exceptional" conditions such as network I/O problems cannot be "proved away" (unlike how in principle you could prove a bound on memory usage of a program), clearly some notion of exceptions is essential for some applications. It follows, IMO, that all functions should be able to propagate exceptions - because any function might in principle be passed a value that cannot be evaluated because an exception has occured. -- Robin From fzuurbie@inter.nl.net Tue, 9 Dec 2003 07:57:01 UT Date: Tue, 9 Dec 2003 07:57:01 UT From: fzuurbie@inter.nl.net fzuurbie@inter.nl.net Subject: [clean-list] Clean in the Real World This is a multi-part message in MIME format. --_----------=_107095662132661 Content-Disposition: inline Content-Length: 1687 Content-Transfer-Encoding: binary Content-Type: text/plain > > Clean lacks exception handling though. If (a part of) an > > application runs out of stack or heap space, the application > > just quits. > > This makes some sense, since Exceptions (by their nature) are not > functional. However, from a pragmatic standpoint I wonder if their lack > may make writing robust software in Clean more difficult. > > Does Clean provide something like the exception model proposed in Simon > Peyton-Jones et. al "A Semantics for Imprecise Exceptions" > (http://research.microsoft.com/Users/simonpj/Papers/imprecise-exn.htm)? > > What is the recommended approach for dealing with exceptional/error > conditions in Clean? Functional language have a history of pushing error situations from run time to compile time. Compile time type checking is one area. Deterministic parallellism is another. Both incur limitations on the programmer, compared with run time typing and non-deterministic parallellism. But they kill vast numbers of errors. In Clean the Sparkle proof tool has emerged: why do you need exception handling if you can prove at compile time that exceptions will never occur? And of course, this will change (limit) the way we program or we will simply be unable to prove the absence of exceptions. When I look around me where I work, software is littered with throwing and catching exceptions. I sometimes wonder whether the programs do anything else at all. The ease with which a programming problem is delegated to an ill understood run time mechanism (exceptions handling that is) sometimes scares me. One should not be allowed to call such programs programs ('written beforehand') at all. Regards Erik Zuurbier --_----------=_107095662132661-- From Jenda@Krynicky.cz Tue, 09 Dec 2003 16:18:27 +0100 Date: Tue, 09 Dec 2003 16:18:27 +0100 From: Jenda Krynicky Jenda@Krynicky.cz Subject: [clean-list] Clean in the Real World From: fzuurbie@inter.nl.net > In Clean the Sparkle proof tool has emerged: why do you need exception > handling if you can prove at compile time that exceptions will never > occur? Can you prove it for the whole OS? Or even the whole net? Exceptions can ocure outside your program. Just a very simple example ... how would you prove that your program is going to have enough memory? > And of course, this will change (limit) the way we program or > we will simply be unable to prove the absenc e of exceptions. > > When I look around me where I work, software is littered with throwing > and catching exceptions. I sometimes wonder whether the programs do > anything else at all. The ease with which a programming problem is > delegated to an ill understood run time mechani sm (exceptions > handling that is) sometimes scares me. One should not be allowed to > call such programs programs ('written beforehand') at all. Exceptions allow you to handle errors at the place where the handling makes sense, which is not necessarily the same place the errors ocure. Exceptions usualy allow you to write much nicer code, instead of passing some status variables around and testing them all the time you just throw an exception and somewhere several levels up in the call stack you handle them. Sure that in a functional language the exceptions would have to work (and would be used) in a very different way that in an imperative language, but I would not be so quick in calling them useless. Jenda ===== Jenda@Krynicky.cz === http://Jenda.Krynicky.cz ===== When it comes to wine, women and song, wizards are allowed to get drunk and croon as much as they like. -- Terry Pratchett in Sourcery From johnvg@cs.kun.nl Tue, 9 Dec 2003 17:14:45 +0100 Date: Tue, 9 Dec 2003 17:14:45 +0100 From: John van Groningen johnvg@cs.kun.nl Subject: [clean-list] Strict lists strike again... Jerzy Karczmarczuk wrote: >Illustrissimi Condottieri: > >A silly, wasteful infinite repetition for unboxed stuff, say Reals: > >rep :: !Real -> [#Real] >rep x = [x : rep x] > >works. But making it just a cycle: > >Rep x = z where > z = [# x : z] > >as the obverloaded Repeat does - >- chokes and dies, yelling horribly. (Clean 2.1, Microsoft Windows), after >having displayed on the console some small number, close to floating underflow. >The system wants even to launch the debugger, so there is some access violation >somewhere in the generated code. The compiler generates incorrect code if the root expression of a function is an unboxed list constructor on a cycle. An improved backend.dll for windows with a fix for this bug is available at: http://www.cs.kun.nl/~clean/download/Clean21/windows/backend.zip Regards, John van Groningen From m.wittebrood@mailbox.kun.nl Tue, 09 Dec 2003 21:12:00 +0100 Date: Tue, 09 Dec 2003 21:12:00 +0100 From: Marco Kesseler m.wittebrood@mailbox.kun.nl Subject: [clean-list] Clean in the Real World >On Mon, Dec 08, 2003 at 03:19:30PM -0800, Brent Fulgham wrote: >> > Clean lacks exception handling though. If (a part of) an >> > application runs out of stack or heap space, the application >> > just quits. >> >> This makes some sense, since Exceptions (by their nature) are not >>functional. > >Well, that's arguable. You can in principle do exceptions as values, >e.g. have everything >return a type which contains a value and a flag to indicate whether >the value is to be >treated as an exception. Exactly. >But that changes the semantics of your program (and how you write it). In theory yes, but not in practice. At the moment, if something goes wrong, you _have_ to pass up the error information explicitly. And this _really_ changes the way you have to write your program. If a language supports exceptions, a lot of this error propagation would happen implicitly, and I suspect that you end up with a cleaner program. >It's not that it can't be done in a functional way, it's that >it's a highly questionable way to do it - for performance and >genericity reasons, >for example. In terms of performance, you'd have all these checks >going on all the time >every time you compute anything at all. If the language and its runtime system supports it, it remains to be seen whether it would (seriously) hurt performance. If some "strict" evaluation takes place on the stack, the compiler might do the same tricks that currently take place in imperative languages. And while matching nodes, the compiler could easily add a check for an exception value at the end of the match sequence where it now complains about non-matching rules. That would not hurt performance a bit. >In terms of genericity, you could either make only some functions >support exceptions >(which would limit their reusability) or make all functions support >exceptions - which >would motivate moving exception machinery into the language itself, >rather than >redundantly putting it everywhere. And then are you going to lose a >little bit of >purity? Well, yes - but in translating a program into >exceptions-as-value style you >in general lose a little bit of purity anyway, namely opacity of >order of evaluation. As long as no exceptions occur, your program will be purer than having to explicitly check for errors all the time. And if they do, well who cares about purity then? Everything is better than just bailing out. And strictly speaking, exceptions-as-values are not impure at all. If you want to, you can already put all data in a "Maybe" type. It is just a lot of coding. >Given that in the real world, "exceptional" conditions such as >network I/O problems >cannot be "proved away" (unlike how in principle you could prove a >bound on memory >usage of a program), clearly some notion of exceptions is essential >for some applications. >It follows, IMO, that all functions should be able to propagate >exceptions - because >any function might in principle be passed a value that cannot be >evaluated because >an exception has occured. Yes. Erik Zuurbier wrote: >When I look around me where I work, software is littered with >throwing and catching >exceptions. I sometimes wonder whether the programs do anything else >at all. The >ease with which a programming problem is delegated to an ill >understood run time >mechanism (exceptions handling that is) sometimes scares me. One >should not be >allowed to call such programs programs ('written beforehand') at all. Exceptions are for the things you _cannot_ catch compile-time. No proof system will ever be able to get rid of those. And if you want to write more than a toy program, you _have_ to deal with them. regards, Marco From arjenw@cs.kun.nl Wed, 10 Dec 2003 11:31:46 +0100 Date: Wed, 10 Dec 2003 11:31:46 +0100 From: Arjen van Weelden arjenw@cs.kun.nl Subject: [clean-list] Clean in the Real World Brent Fulgham wrote: >>Clean lacks exception handling though. If (a part of) an >>application runs out of stack or heap space, the application >>just quits. > > > This makes some sense, since Exceptions (by their nature) are not functional. However, from a pragmatic standpoint I wonder if their lack may make writing robust software in Clean more difficult. > > Does Clean provide something like the exception model proposed in Simon Peyton-Jones et. al "A Semantics for Imprecise Exceptions" (http://research.microsoft.com/Users/simonpj/Papers/imprecise-exn.htm)? Clean 2.1 for Windows comes with a small library (Libraries\ ExceptionsWindows\StdException) that implements user-defined (synchronous) imprecise exceptions using machine dependent ABC-code and Dynamics. At least, it ought to implement just that, but it needs more users to really test it. It should problably be rewritten in assembly, incorporated into Clean's run-time system, and ported to the other platforms. regards, Arjen From willeralves@yahoo.com.br Wed, 10 Dec 2003 07:47:16 -0300 (ART) Date: Wed, 10 Dec 2003 07:47:16 -0300 (ART) From: =?iso-8859-1?q?Alves=20da=20Silva=20Cruz=20Willer?= willeralves@yahoo.com.br Subject: [clean-list] Multimedia - Again --0-1063162445-1071053236=:21988 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit Hello People, Recently, I've posted a message in this list about using Media Player with Clean. Unfortunately, I had no answers... But I'm a very insistent person. :-) So, even I need to open the Media player in a separate window, someone could help me about how could I interface the two applications? I know I can execute the plugin trough command line, but I need to know, for example, if the user forwarded or rewinded the video and I still don't know how to do it... Any idea would be very appreciated. About Clean in the real world topic, I can say I've done some cool stuff in Clean. My recent jobs with it includes an Instrumental Dictionary, a Triphasic Electric Induction Machines Simulator and several programs for Signal Analisys. I think that, handling run time errors, Clean could be used for most "Real World" applications today... Thanks, Willer Alves Uberlandia, MG - Brazil --------------------------------- Yahoo! Mail - 6MB, anti-spam e antivírus gratuito. Crie sua conta agora! --0-1063162445-1071053236=:21988 Content-Type: text/html; charset=iso-8859-1 Content-Transfer-Encoding: 8bit
Hello People,
 
Recently, I've posted a message in this list about using Media Player with Clean. Unfortunately, I had no answers... But I'm a very insistent person. :-) So, even I need to open the Media player in a separate window, someone could help me about how could I interface the two applications? I know I can execute the plugin trough command line, but I need to know, for example, if the user forwarded or rewinded the video and I still don't know how to do it...
 
Any idea would be very appreciated.
 
About Clean in the real world topic, I can say I've done some cool stuff in Clean. My recent jobs with it includes an Instrumental Dictionary, a Triphasic Electric Induction Machines Simulator and several programs for Signal Analisys. I think that, handling run time errors, Clean could be used for most "Real World" applications today...
 
Thanks,
 
Willer Alves
Uberlandia, MG - Brazil



Yahoo! Mail - 6MB, anti-spam e antivírus gratuito. Crie sua conta agora! --0-1063162445-1071053236=:21988-- From willeralves@yahoo.com.br Thu, 11 Dec 2003 12:00:43 -0300 (ART) Date: Thu, 11 Dec 2003 12:00:43 -0300 (ART) From: =?iso-8859-1?q?Alves=20da=20Silva=20Cruz=20Willer?= willeralves@yahoo.com.br Subject: [clean-list] mod function --0-911963716-1071154843=:83587 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit Hello people, It looks like the instance of "mod" function is missing in the StdInt on Clean 2.0.2 (Win version): Start :: Int Start = 2 mod 4 Compiler: Overloading error: "mod" no instance available of type Int I changed it to: mod :: Int Int -> Int mod a b = a - (a/b)*b But I think it is a little bit dirty trick :-). Willer Alves Uberlandia, MG - Brazil --------------------------------- Yahoo! Mail - 6MB, anti-spam e antivírus gratuito. Crie sua conta agora! --0-911963716-1071154843=:83587 Content-Type: text/html; charset=iso-8859-1 Content-Transfer-Encoding: 8bit
Hello people,
 
It looks like the instance of "mod" function is missing in the StdInt on Clean 2.0.2 (Win version):
 
Start :: Int
Start = 2 mod 4
Compiler: Overloading error: "mod" no instance available of type Int
 
I changed it to:
 
mod :: Int Int -> Int
mod a b = a - (a/b)*b
 
But I think it is a little bit dirty trick :-).
 
Willer Alves
Uberlandia, MG - Brazil



Yahoo! Mail - 6MB, anti-spam e antivírus gratuito. Crie sua conta agora! --0-911963716-1071154843=:83587-- From ronny@cs.kun.nl Thu, 11 Dec 2003 18:46:29 +0100 Date: Thu, 11 Dec 2003 18:46:29 +0100 From: Ronny Wichers Schreur ronny@cs.kun.nl Subject: [clean-list] mod function Alves writes (to the Clean mailing list): > It looks like the instance of "mod" function is missing in the > StdInt on Clean 2.0.2 (Win version): Yes, that's deliberate. The mod function had the wrong semantics for negative arguments. We didn't just want to change the semantics and (perhaps silently) break things. That's why we removed it to signal the change to Clean programmers. It will reappear with proper semantics in a future version. In most situations mod is only used with positive arguments, in which case you can use the function rem instead. Cheers, Ronny Wichers Schreur From fzuurbie@inter.nl.net Thu, 11 Dec 2003 22:49:44 +0100 (MET) Date: Thu, 11 Dec 2003 22:49:44 +0100 (MET) From: Erik Zuurbier fzuurbie@inter.nl.net Subject: [clean-list] Exceptions handling again Jenda Krynicky wrote: "Just a very simple example ... how would you prove that your program is going to have enough memory?" For most regular programs it will be hard or impossible. That's why you may need to change (improve?) your program so that you could prove it. Jenda Krynicky also wrote: "Exceptions allow you to handle errors at the place where the handling makes sense, which is not necessarily the same place the errors occur. Exceptions usualy allow you to write much nicer code, instead of passing some status variables around and testing them all the time you just throw an exception and somewhere several levels up in the call stack you handle them." This is what we all know about exception handling. Speculative evaluation strategies (for instance Optimistic Evaluation - described in a paper by Robert Ennals and Simon Peyton Jones) show us that you can sometimes pursue a line of evaluation and then, for whatever reason, stop, back out and try something else. In my opinion, large classes of what is usually seen as exceptions, could be handled this way: when an integer overflow is encountered, the program could back out and retry the same calculation with an infinite precision library. When the language supports deterministic parallellism, as one Clean implementation by Marco Kesseler once demonstrated, alternatives to pursue may be more abundant. Marco Kesseler wrote to me on 12 march 2003 (translation from Dutch): "Say processor A assigns evaluation of an expression to processor B and then the communication line between the two dies: - what keeps processor A from deciding after all to evaluate the expression itself, or assign it to processor C? - what keeps processor B from halting evaluation of this expression and just throwing it away? B could even use a timeout interval (the way webservers handle sessions)." The TCP/IP has a marvelous mechanism: if I understood it well, a sender resends a packet if it does not get an acknowledgement back within a time interval that depends on the mean and variance of the turn-around time experienced sofar. It thereby strikes a balance between network load (by minimizing the number of resends) and communication speed (by minimizing the delay of a resend). This mechanism probably catches huge numbers of exceptions without me knowing. But then a communication line completely dies and this mechanism does not help a bit. I like to think the internet has other protocols that seek alternative communication routes when that happens. And what does CiteSeer? It dumps an error message back on me: "Server busy. Try later." Why should that happen? I envision a browser that catches that one and does the try latering itself - a la the resends of TCP/IP - and I would only see a window that is waiting for a response. In the mean time I can work in other windows and only if/when I lose patience would I close the CiteSeer window (withdraw the redex). I have seen too many examples of software that gives up too early, mostly because it was too expensive to program for the alternatives. I am perfectly aware that in the end there will be a moment when all conceivable alternatives have been tried in vain. Then the program is allowed to quit. But not earlier. Even if a program is waiting for an Oracle database that died and needs operator attention (don't ask me why, but it happens all the time where I work) the program should not quit. Instead I can imagine an OS-message to the operator, who restarts the database, after which my program just resumes its evaluation. Same with communication lines. Even with database hardware failures: the operator could backup on a different machine, rerun the logged transactions and then resume my program. My conclusion: yes we may need classical exceptions handling for a few years to come, but that should not be the end of it. A lot more automatic recovery support could be developed so that an applications programmer would scarcely need to explicitly program exceptions handling. Regards Erik Zuurbier From claus.reinke@talk21.com Fri, 12 Dec 2003 01:03:43 -0000 Date: Fri, 12 Dec 2003 01:03:43 -0000 From: Claus Reinke claus.reinke@talk21.com Subject: [clean-list] Exceptions handling again It's often useful to look into what other FPLs do, for reference. Erlang, for example, puts a premium not only on fault-avoidance, but also on fault-tolerance: something will go wrong eventually if you make the software/hardware combination complex and long-running enough (such as the backbone of the UK phone system). _When_ it does, it's no good to shut down everything, sit in the corner with red lights blinking and flashing the message "this should never have happened".. Erlang does support exception handling, but a favourite line is actually that no process should do its own exception handling: instead, there'll be processes doing the processing, and other processes (preferably on separate machines) that do the supervising. If a supervised process encounters a situation it wasn't programmed to deal with, it is _not_ supposed to try and make up something sensible, but it is supposed to crash (that takes some getting used to, but remember that there are supposed to be supervisors to deal with such local crashes;-). Only that process will crash, not the whole system, and its supervisor process will be notified and can then decide whether to log the problem and "try again" or what else to do. Instead of trying to repeat the arguments here, I'll just refer to Joe Armstrong's recent PhD thesis, in which he tries to explain much of his Erlang philosophy, and how it informed the design of Erlang and its libraries (the latter encapsulate most of the fault-tolerance, error-handling, and even concurrency issues, so that Erlang application programmers scarcely need to program these things explicitly - they simply instantiate generic design patterns with application-specific code): making reliable systems in the presence of software errors http://www.sics.se/~joe/index.html Sounds like what you were looking for, doesn't it?-) Now if only someone would give us the best aspects of Clean, Haskell, and Erlang, combined in a single, elegant language design.. Cheers, Claus > Marco Kesseler wrote to me on 12 march 2003 (translation from Dutch): > "Say processor A assigns evaluation of an expression to processor B and > then the communication line between the two dies: > - what keeps processor A from deciding after all to evaluate the expression > itself, or assign it to processor C? > - what keeps processor B from halting evaluation of this expression and > just throwing it away? B could even use a timeout interval (the way > webservers handle sessions)." .. > I have seen too many examples of software that gives up too early, mostly > because it was too expensive to program for the alternatives. I am > perfectly aware that in the end there will be a moment when all conceivable > alternatives have been tried in vain. Then the program is allowed to quit. > But not earlier. Even if a program is waiting for an Oracle database that > died and needs operator attention (don't ask me why, but it happens all the > time where I work) the program should not quit. Instead I can imagine an > OS-message to the operator, who restarts the database, after which my > program just resumes its evaluation. Same with communication lines. Even > with database hardware failures: the operator could backup on a different > machine, rerun the logged transactions and then resume my program. .. > My conclusion: yes we may need classical exceptions handling for a few > years to come, but that should not be the end of it. A lot more automatic > recovery support could be developed so that an applications programmer > would scarcely need to explicitly program exceptions handling. From fzuurbie@inter.nl.net Fri, 12 Dec 2003 07:45:07 UT Date: Fri, 12 Dec 2003 07:45:07 UT From: fzuurbie@inter.nl.net fzuurbie@inter.nl.net Subject: [clean-list] Exceptions handling again This is a multi-part message in MIME format. --_----------=_1071215107186585 Content-Disposition: inline Content-Length: 753 Content-Transfer-Encoding: binary Content-Type: text/plain Thanks Claus for pointing me to this work. You won't hear me say a word about exception handling until I read it. Erik Zuurbier > Joe Armstrong's recent PhD thesis, in which he tries to explain > much of his Erlang philosophy, and how it informed the design > of Erlang and its libraries (the latter encapsulate most of the > fault-tolerance, error-handling, and even concurrency issues, > so that Erlang application programmers scarcely need to program > these things explicitly - they simply instantiate generic design > patterns with application-specific code): > > making reliable systems in the presence of software errors > http://www.sics.se/~joe/index.html > > Sounds like what you were looking for, doesn't it?-) --_----------=_1071215107186585-- From karczma@info.unicaen.fr Fri, 12 Dec 2003 09:19:27 +0100 Date: Fri, 12 Dec 2003 09:19:27 +0100 From: Jerzy Karczmarczuk karczma@info.unicaen.fr Subject: [clean-list] mod function Ronny Wichers Schreur wrote: > Alves writes (to the Clean mailing list): > >> It looks like the instance of "mod" function is missing in the >> StdInt on Clean 2.0.2 (Win version): > > > Yes, that's deliberate. The mod function had the wrong semantics > for negative arguments. We didn't just want to change the semantics > and (perhaps silently) break things. That's why we removed it to > signal the change to Clean programmers. But - unless I am mistaken - it is still present in the modified environment for Sparkle. Is it deliberate as well, or the system development proceeded along two weakly communicating streams? ====================================== When I am already here, I pose a different question, just to calm my spirits. You say since the beginning that the Clean compiler has been optimized for speed. However, recently I compiled some hundreds times some small test programs, regretting truly that I don't have a Clean interactive interpreter by hand... Usually the compiler when it starts, it spends an inordinate amount of time doing some administrative chores, initialization perhaps. Nothing happens, even the disk remains quiet. After many seconds it starts its febrile module checking, recompilation, producing diagnostics, etc. Sometimes, when I do some correction to the program, this initial period is *much* shorter, the compilation starts almost immediately. And sometimes not... What happens, Señores Commandantes? Such behaviour is a little disturbing, being irregular. Jerzy Karczmarczuk From ronny@cs.kun.nl Fri, 12 Dec 2003 10:27:31 +0100 Date: Fri, 12 Dec 2003 10:27:31 +0100 From: Ronny Wichers Schreur ronny@cs.kun.nl Subject: [clean-list] mod function Jerzy Karczmarczuk writes (to the Clean Discussion list): > But - unless I am mistaken -[mod] is still present in > the modified environment for Sparkle. Is it deliberate > as well, or the system development proceeded along two > weakly communicating streams? The latter. The Sparkle environment differs in two ways from the Clean environment: - different definitions with identical semantics (for example non-accumulating reverse in Sparkle); - some extra eval functions in StdSparkle; - different semantics (the functions drop and take from StdList). The Sparkle environment should be layered on top of the Clean enviroment: it should only contain the modules in which it differs. The drop/take issue is a bit more controversial. My proposal is to change both Clean's and Sparkle's definitions to the Haskell equivalents: this means that they will be strict in their integer argument (as in Clean) and have nicer properties with negative arguments (as in Sparkle). Apart from this, the Clean system and Sparkle are pretty much in harmony. For example Sparkle now always uses the same frontend as the Clean compiler and is compiled with the latest Clean compiler. Cheers, Ronny Wichers Schreur From ronny@cs.kun.nl Fri, 12 Dec 2003 11:42:44 +0100 Date: Fri, 12 Dec 2003 11:42:44 +0100 From: Ronny Wichers Schreur ronny@cs.kun.nl Subject: Compile times (was: [clean-list] mod function) Jerzy Karczmarczuk writes (to the Clean mailing list):: > What happens, Señores Commandantes? [The unpredictable > compile time] is a little disturbing, being irregular. Sometimes updates for a project in the Windows IDE can take very long. The IDE's compilation process is driven by events, and occasionally null events don't get through to the IDE. This situation is easily recognised and remedied: generate some extra events by moving your mouse and the compilation process will speed up. Another factor for irregular behaviour is caching. I think you would have noticed disk activity if the disk cache was the explanation. The compiler caches imported dcl modules, but only for the duration of one update and not between two bring-up-to-dates. I don't recognize the specific behaviour you're describing (a long period of seeming inactivity, followed by frantic compilation). If you observe this regularly, it would help if you could open Task Manager > Processes, sort by CPU time, and report to us which process is on top. Cheers, Ronny Wichers Schreur From olefevre@usa.net Fri, 12 Dec 2003 17:31:56 +0100 Date: Fri, 12 Dec 2003 17:31:56 +0100 From: Olivier Lefevre olefevre@usa.net Subject: [[clean-list] Exceptions handling again] > My conclusion: yes we may need classical exceptions handling for a > few years to come, but that should not be the end of it. A lot more > automatic recovery support could be developed so that an applications > programmer would scarcely need to explicitly program exceptions > handling. As you are yourself conceding, you will never be able to automate everything: "scarcely" is not the same as "never". Thus there will always be a need for a mechanism of last resort. In a non-parallel setting, exceptions are not such a bad scheme. -- O.L. From igouy2@yahoo.com Fri, 12 Dec 2003 09:49:09 -0800 (PST) Date: Fri, 12 Dec 2003 09:49:09 -0800 (PST) From: Isaac Gouy igouy2@yahoo.com Subject: [clean-list] Exceptions handling again > > Joe Armstrong's recent PhD thesis There's a reference to this paper: "Why Do Computers Stop and What Can Be Done About It?" Jim Gray, 1985 http://www.hpl.hp.com/techreports/tandem/TR-85.7.html which provides the basic principles, and some wonderful terms- Bohrbugs and Heisenbugs. (English speakers might be amused to note that an early version of the paper was presented at Erlangen...) __________________________________ Do you Yahoo!? Protect your identity with Yahoo! Mail AddressGuard http://antispam.yahoo.com/whatsnewfree From brent.fulgham@xpsystems.com Fri, 12 Dec 2003 11:04:36 -0800 Date: Fri, 12 Dec 2003 11:04:36 -0800 From: Brent Fulgham brent.fulgham@xpsystems.com Subject: [clean-list] mod function > Usually the compiler when it starts, it spends an inordinate amount of > time doing some administrative chores, initialization perhaps. Nothing > happens, even the disk remains quiet. After many seconds it starts its > febrile module checking, recompilation, producing diagnostics, etc. > Sometimes, when I do some correction to the program, this initial > period is *much* shorter, the compilation starts almost immediately. > And sometimes not... I don't see this behavior using the command-line compiler under Linux. Perhaps it's something in the IDE framework that is taking so long. I've actually been quite amazed at how fast the compiler is. -Brent From m.wittebrood@mailbox.kun.nl Sun, 14 Dec 2003 00:02:33 +0100 Date: Sun, 14 Dec 2003 00:02:33 +0100 From: Marco Kesseler m.wittebrood@mailbox.kun.nl Subject: [clean-list] Clean in the Real World Arjen van Weelden wrote: >Brent Fulgham wrote: >> Does Clean provide something like the exception model proposed in >>Simon Peyton-Jones et. al "A Semantics for Imprecise Exceptions" >>(http://research.microsoft.com/Users/simonpj/Papers/imprecise-exn.htm)? > >Clean 2.1 for Windows comes with a small library (Libraries\ >ExceptionsWindows\StdException) that implements user-defined >(synchronous) imprecise exceptions using machine dependent ABC-code and >Dynamics. At least, it ought to implement just that, but it needs more >users to really test it. It should problably be rewritten in assembly, >incorporated into Clean's run-time system, and ported to the other >platforms. Having read a part of the paper of Simon Peyton Jones et al. about imprecise exceptions, I must say that this is not exactly what I had in mind myself. A main issue in the paper seems to be - if you implement exceptions via stack trimming - that "getException (a + b)" may not have the same value as "getException (b + a)", if both a and b lead to an exceptional - but different - value. It depends on which one gets evaluated first, and often the compiler decides things for you. The writers end up putting getExeption in the IO Monad, and then suddenly it _is_ allowed to non-deterministically choose one exception value, supposedly without hurting referential transparancy. If all the interesting stuff must end up in the IO Monad I'd rather just use a real imperative language (sorry if I hurt anybodies feelings, but some Monad tricks are getting on my nerves). And it is needless too. All it takes is a cheap syntactical change: do NOT pass the guarded expression as an argument to a function that checks for exceptions. Instead of getException(a + b) write: f a b = a + b catch e = ... g a b = a + b catch e = ... Now, catching the exception value has become decoupled from the (a + b) expression. Instead, it becomes associated with f and g. And "f a b" does _not_ need to have the same value as "g a b", because f and g are different functions. The only thing that the compiler needs to guarantee is that f a b always delivers the same exceptional value when applied to the same arguments. So, the expression (a + b) must always be evaluated in the same way within a single program. As far as I know this is normally so in non-concurrent evaluation schemes for "synchronous" exceptions. regards, Marco From bfulgham@debian.org Sat, 13 Dec 2003 23:19:05 -0800 Date: Sat, 13 Dec 2003 23:19:05 -0800 From: Brent A. Fulgham bfulgham@debian.org Subject: [clean-list] Clean in the Real World On Saturday 13 December 2003 3:02 pm, Marco Kesseler wrote: > A main issue in the paper seems to be - if you implement exceptions > via stack trimming - that "getException (a + b)" may not have the > same value as "getException (b + a)", if both a and b lead to an > exceptional - but different - value. It depends on which one gets > evaluated first, and often the compiler decides things for you. [ ... snip ... ] > And it is needless too. All it takes is a cheap syntactical change: > do NOT pass the guarded expression as an argument to a function that > checks for exceptions. Instead of getException(a + b) write: > > f a b > = a + b > catch e = ... > > g a b > = a + b > catch e = ... > > Now, catching the exception value has become decoupled from the (a + > b) expression. Instead, it becomes associated with f and g. And "f a > b" does _not_ need to have the same value as "g a b", because f and g > are different functions. I have no quarrel with this approach -- in fact, it seems very similar to SML syntax (which might actually merge well with Clean's underlying semantics, if the great language genealogical diagram is correct... see http://people.mandrakesoft.com/~prigaux/language-study/diagram.png) > The only thing that the compiler needs to guarantee is that f a b > always delivers the same exceptional value when applied to the same > arguments. So, the expression (a + b) must always be evaluated in the > same way within a single program. As far as I know this is normally > so in non-concurrent evaluation schemes for "synchronous" exceptions. Is the order of evaluation guaranteed in Clean? In many languages it is implementation-specific (various Scheme systems will evaluate in different orders.) Of course, your point is that they just must be consistent within a single program which is far more likely. -Brent From m.wittebrood@mailbox.kun.nl Sun, 14 Dec 2003 15:47:48 +0100 Date: Sun, 14 Dec 2003 15:47:48 +0100 From: Marco Kesseler m.wittebrood@mailbox.kun.nl Subject: [clean-list] Clean in the Real World >On Saturday 13 December 2003 3:02 pm, Marco Kesseler wrote: >> g a b >> = a + b >> catch e = ... >> >> Now, catching the exception value has become decoupled from the (a + >> b) expression. Instead, it becomes associated with f and g. And "f a >> b" does _not_ need to have the same value as "g a b", because f and g >> are different functions. > >I have no quarrel with this approach -- in fact, it seems very >similar to SML >syntax (which might actually merge well with Clean's underlying >semantics, if >the great language genealogical diagram is correct... >see http://people.mandrakesoft.com/~prigaux/language-study/diagram.png) Nice diagram, although I think that modern Clean has more in common with Haskell than the diagram suggests >> The only thing that the compiler needs to guarantee is that f a b >> always delivers the same exceptional value when applied to the same >> arguments. So, the expression (a + b) must always be evaluated in the >> same way within a single program. As far as I know this is normally >> so in non-concurrent evaluation schemes for "synchronous" exceptions. > >Is the order of evaluation guaranteed in Clean? Well, no. Strictness analysis may change the evaluation order (and concurrency too). >In many languages it is >implementation-specific (various Scheme systems will evaluate in different >orders.) Of course, your point is that they just must be consistent within a >single program which is far more likely. As far as I know, within a single program it will be fixed for "sequential" implementations. In fact, the imprecise exception paper also mentions that successive runs of the same pogram will in practice return the same exceptions, and that recompiling with different optimisation settings may lead to a different exception being thrown. They also compare their solution to ML and "speculate" that having to do exception handling in the IO Monad is not awkward in practice. Well, I seriously doubt that. I think that being able to encapsulate exception handling completely within any function - like ML allows - is _essential_. I do have to admit however that the solution that I proposed cannot deal with asynchronous exceptions, such as a user pressing "ctrl C" . These however, belong to the IO arena anyway I think. So that does not really worry me. There are a few things that I am not yet sure of: * Should all expression in principle be able to throw an exception? If this is not the case, we should use the type system to tell us which expressions may throw exceptions and which won't (which is nice!). This however can have big consequences if you change an expression so that it starts throwing exceptions. You may have to change a lot of types then, similar to the effects that adding uniqueness, or Monads may have. * Is stack trimming really the right way to implement exception propagation? Suppose that an expression is evalutated as part of a pattern match, and it throws an exception. Should the exception then be caught (stack trimming), or should matching fail, and the next alternative tried? (this may have some intricate semantical consequences). Marco From fjh@cs.mu.oz.au Mon, 15 Dec 2003 11:34:48 +1100 Date: Mon, 15 Dec 2003 11:34:48 +1100 From: Fergus Henderson fjh@cs.mu.oz.au Subject: [clean-list] Clean in the Real World On 14-Dec-2003, Marco Kesseler wrote: > > Having read a part of the paper of Simon Peyton Jones et al. about > imprecise exceptions, I must say that this is not exactly what I had > in mind myself. > > A main issue in the paper seems to be - if you implement exceptions > via stack trimming - that "getException (a + b)" may not have the > same value as "getException (b + a)", if both a and b lead to an > exceptional - but different - value. It depends on which one gets > evaluated first, and often the compiler decides things for you. > > The writers end up putting getExeption in the IO Monad, and then > suddenly it _is_ allowed to non-deterministically choose one > exception value, supposedly without hurting referential transparancy. > If all the interesting stuff must end up in the IO Monad I'd rather > just use a real imperative language (sorry if I hurt anybodies > feelings, but some Monad tricks are getting on my nerves). It's not really necessary to put getException in the IO Monad. The IO Monad provides both nondeterminism and I/O, and here we only need nondeterminism. So another alternative would be to have a separate monad for nondeterminism, and to put getException in that monad instead. (See for some more details.) The Haskell implementors decided not to do that, because they considered it simpler to just use the IO Monad. But they way that they did it is not the only possibility. > And it is needless too. All it takes is a cheap syntactical change: > do NOT pass the guarded expression as an argument to a function that > checks for exceptions. Instead of getException(a + b) write: > > f a b > = a + b > catch e = ... > > g a b > = a + b > catch e = ... I do not agree that this solves the problem. It breaks fundamental properties of a language based on lambda calculus. > Now, catching the exception value has become decoupled from the (a + > b) expression. Instead, it becomes associated with f and g. And "f a > b" does _not_ need to have the same value as "g a b", because f and g > are different functions. A major drawback of this scheme is that function definitions can no longer be seen as equivalent to variable bindings. In Haskell, the semantics of a function definition f a b = a + b is defined by the translation into "Core Haskell" as f = \ a b -> a + b as is appropriate for a language based on lambda calculus. But with your approach, there is no way that such a translation could be used for functions defined with a catch clause. You could extend lambda expressions with catch clauses, but there would be no way of defining a syntax/semantics for lambda expressions with catch clauses that did not violate referential transparency. > The only thing that the compiler needs to guarantee is that f a b > always delivers the same exceptional value when applied to the same > arguments. So, the expression (a + b) must always be evaluated in the > same way within a single program. As far as I know this is normally > so in non-concurrent evaluation schemes for "synchronous" exceptions. No, that is not the case. Normal implementations may often inline or specialize functions such as `f' or `g' above, and may then apply different optimizations to the different copies of the function due to their use in different contexts. This may then result in different exceptions being thrown. -- Fergus Henderson | "I have always known that the pursuit The University of Melbourne | of excellence is a lethal habit" WWW: | -- the last words of T. S. Garp. From arjenw@cs.kun.nl Mon, 15 Dec 2003 09:36:45 +0100 Date: Mon, 15 Dec 2003 09:36:45 +0100 From: Arjen van Weelden arjenw@cs.kun.nl Subject: [clean-list] Clean in the Real World Marco Kesseler wrote: > Arjen van Weelden wrote: > >>Brent Fulgham wrote: >> >>>Does Clean provide something like the exception model proposed in >>>Simon Peyton-Jones et. al "A Semantics for Imprecise Exceptions" >>>(http://research.microsoft.com/Users/simonpj/Papers/imprecise-exn.htm)? >> >>Clean 2.1 for Windows comes with a small library (Libraries\ >>ExceptionsWindows\StdException) that implements user-defined >>(synchronous) imprecise exceptions using machine dependent ABC-code and >>Dynamics. At least, it ought to implement just that, but it needs more >>users to really test it. It should problably be rewritten in assembly, >>incorporated into Clean's run-time system, and ported to the other >>platforms. > > > Having read a part of the paper of Simon Peyton Jones et al. about > imprecise exceptions, I must say that this is not exactly what I had > in mind myself. > > A main issue in the paper seems to be - if you implement exceptions > via stack trimming - that "getException (a + b)" may not have the > same value as "getException (b + a)", if both a and b lead to an > exceptional - but different - value. It depends on which one gets > evaluated first, and often the compiler decides things for you. > > The writers end up putting getExeption in the IO Monad, and then > suddenly it _is_ allowed to non-deterministically choose one > exception value, supposedly without hurting referential transparancy. > If all the interesting stuff must end up in the IO Monad I'd rather > just use a real imperative language (sorry if I hurt anybodies > feelings, but some Monad tricks are getting on my nerves). > As I see it, catching exceptions is only non-deterministic between compilations. There are more functions in the Clean distribution that ought to use the !*World -> *World style, but since they are fixed for a single run of a program (like getCommandLine, or things like getProcessId) they don't. I don't like putting it in the IO monad/!*W->*W, and it don't like disturbing ref.transp., but in this case the second options suits me best. I am thinking about changing the 'unsafeX' functions in the StdException library to 'X', and the 'X' functions to 'evenSaferX'. Just like any other expressions in Clean, you cannot assume much about the evaluation order, so don't! Make sure that the code handles any exception (from both a and b). regards, Arjen From m.wittebrood@mailbox.kun.nl Mon, 15 Dec 2003 10:25:07 +0100 Date: Mon, 15 Dec 2003 10:25:07 +0100 From: Marco Kesseler m.wittebrood@mailbox.kun.nl Subject: [clean-list] Clean in the Real World Arjen Wrote: >As I see it, catching exceptions is only non-deterministic between >compilations. There are more functions in the Clean distribution that >ought to use the !*World -> *World style, but since they are fixed for a >single run of a program (like getCommandLine, or things like >getProcessId) they don't. I don't like putting it in the IO >monad/!*W->*W, and it don't like disturbing ref.transp., but in this >case the second options suits me best. >I am thinking about changing the 'unsafeX' functions in the StdException >library to 'X', and the 'X' functions to 'evenSaferX'. >Just like any other expressions in Clean, you cannot assume much about >the evaluation order, so don't! Make sure that the code handles any >exception (from both a and b). Well, if you just consider the "disaster" type of exception, hurting referential transparency _seems_ like a minor issue compared to the good old abort. But for the "alternative return" type of exception this is clearly different, as this would just be an alternative to passing up error information yourself. IF you take the non-deterministic approach, it is up to the programmer to map _any_ exception to the same result, so that referential transparency is restored at the catch. But I'd rather not, if it is not needed. regards, Marco P.S. I will write an answer to Fergus' mail too, but my attention is needed elsewhere now. From fjh@cs.mu.oz.au Mon, 15 Dec 2003 22:50:19 +1100 Date: Mon, 15 Dec 2003 22:50:19 +1100 From: Fergus Henderson fjh@cs.mu.oz.au Subject: [clean-list] Clean in the Real World On 15-Dec-2003, Arjen van Weelden wrote: > As I see it, catching exceptions is only non-deterministic between > compilations. You may see it that way, and it might perhaps even be true for the current Clean implementation, but that's not the case in general. IMHO imposing that as a requirement would unduly restrict the compiler's freedom to optimize code. It would rule out or significantly restrict important categories of implementations, including those that do automatic parallelization, and those that initially evaluate code naively and then apply optimizations based on run-time profiling feedback. -- Fergus Henderson | "I have always known that the pursuit The University of Melbourne | of excellence is a lethal habit" WWW: | -- the last words of T. S. Garp. From fjh@cs.mu.oz.au Mon, 15 Dec 2003 23:04:13 +1100 Date: Mon, 15 Dec 2003 23:04:13 +1100 From: Fergus Henderson fjh@cs.mu.oz.au Subject: [clean-list] Clean in the Real World On 15-Dec-2003, Marco Kesseler wrote: > if you just consider the "disaster" type of exception, hurting > referential transparency _seems_ like a minor issue compared to the > good old abort. Why make this choice? We don't need to sacrifice referential transparency in order to prevent disasters. Why not have referential transparency _and_ catch exceptions? Given that Clean is designed around the idea of pure functional programming, preserving the properties of pure functional programming seems important. If you don't care about those properties, then there are plenty of other languages which you can use -- for example OCaml. -- Fergus Henderson | "I have always known that the pursuit The University of Melbourne | of excellence is a lethal habit" WWW: | -- the last words of T. S. Garp. From m.wittebrood@mailbox.kun.nl Mon, 15 Dec 2003 14:29:58 +0100 Date: Mon, 15 Dec 2003 14:29:58 +0100 From: Marco Kesseler m.wittebrood@mailbox.kun.nl Subject: [clean-list] Clean in the Real World >On 15-Dec-2003, Marco Kesseler wrote: >> if you just consider the "disaster" type of exception, hurting >> referential transparency _seems_ like a minor issue compared to the >> good old abort. > >Why make this choice? We don't need to sacrifice referential transparency >in order to prevent disasters. Why not have referential transparency >_and_ catch exceptions? > >Given that Clean is designed around the idea of pure functional programming, >preserving the properties of pure functional programming seems important. >If you don't care about those properties, then there are plenty of other >languages which you can use -- for example OCaml. I do care. I also said: >IF you take the non-deterministic approach, it is up to the >programmer to map _any_ exception to the same result, so that >referential transparency is restored at the catch. > >But I'd rather not, if it is not needed. >-- >Fergus Henderson | "I have always known that the pursuit >The University of Melbourne | of excellence is a lethal habit" >WWW: | -- the last words of T. S. Garp. > > >_______________________________________________ >clean-list mailing list >clean-list@cs.kun.nl >http://www.cs.kun.nl/mailman/listinfo/clean-list From m.wittebrood@mailbox.kun.nl Mon, 15 Dec 2003 15:02:25 +0100 Date: Mon, 15 Dec 2003 15:02:25 +0100 From: Marco Kesseler m.wittebrood@mailbox.kun.nl Subject: [clean-list] Clean in the Real World >On 15-Dec-2003, Arjen van Weelden wrote: >> As I see it, catching exceptions is only non-deterministic between >> compilations. > >You may see it that way, and it might perhaps even be true for the >current Clean implementation, but that's not the case in general. >IMHO imposing that as a requirement would unduly restrict the >compiler's freedom to optimize code. As long as it optimises at compile time, it is free to do whatever it wants, except at a few locations that hold catch statements. >It would rule out or significantly restrict important categories of >implementations, including those that do automatic parallelization, >and those that initially evaluate code naively and then apply >optimizations based on run-time profiling feedback. As soon as we get these, I am willing to think about other ways to deal with exceptional situations. Apart from that, the same non-deterministic effects will occur in the Monadic solution. The fact that this is theoretically allowed may not help the average programmer in reasoning about his program. (which does _not_ imply that I am against soundness) And then, there is still the possibility to enforce catch statements to always deliver the same constant expression on any exception. >-- >Fergus Henderson | "I have always known that the pursuit >The University of Melbourne | of excellence is a lethal habit" >WWW: | -- the last words of T. S. Garp. > > >_______________________________________________ >clean-list mailing list >clean-list@cs.kun.nl >http://www.cs.kun.nl/mailman/listinfo/clean-list From fjh@cs.mu.oz.au Tue, 16 Dec 2003 01:37:52 +1100 Date: Tue, 16 Dec 2003 01:37:52 +1100 From: Fergus Henderson fjh@cs.mu.oz.au Subject: [clean-list] Clean in the Real World On 15-Dec-2003, Marco Kesseler wrote: > >On 15-Dec-2003, Arjen van Weelden wrote: > >> As I see it, catching exceptions is only non-deterministic between > >> compilations. > > > >You may see it that way, and it might perhaps even be true for the > >current Clean implementation, but that's not the case in general. > >IMHO imposing that as a requirement would unduly restrict the > >compiler's freedom to optimize code. > > As long as it optimises at compile time, it is free to do whatever it > wants, except at a few locations that hold catch statements. That's not correct. If you want to preserve the nice properties of pure functional programming, then optimization would be inhibited in any code which might be called from a catch statement. Since it is common practice to put an exception handler at the very top level, this would typically mean the entire program. If you don't inhibit such optimizations, then you would end up in the situation where applying simple and obvious transformations such as replacing a variable with its definition might change the program's behaviour. > And then, there is still the possibility to enforce catch statements > to always deliver the same constant expression on any exception. Not if you permit statements that might not halt. Otherwise the compiler in general still can't reorder code, such as the evaluation of x and y in "x + y", because "catch(1/0 + loop)" will terminate whereas "catch(loop + 1/0)" will loop. Automatic termination analysis is still not yet good enough to want to rely on it -- after all, this is the classic halting problem! -- Fergus Henderson | "I have always known that the pursuit The University of Melbourne | of excellence is a lethal habit" WWW: | -- the last words of T. S. Garp. From m.wittebrood@mailbox.kun.nl Mon, 15 Dec 2003 16:50:40 +0100 Date: Mon, 15 Dec 2003 16:50:40 +0100 From: Marco Kesseler m.wittebrood@mailbox.kun.nl Subject: [clean-list] Clean in the Real World It's hard to keep up with you Fergus! I still have to write an answer to your original response... Fergus wrote >On 15-Dec-2003, Marco Kesseler wrote: >> >On 15-Dec-2003, Arjen van Weelden wrote: >> >> As I see it, catching exceptions is only non-deterministic between >> >> compilations. >> > >> >You may see it that way, and it might perhaps even be true for the >> >current Clean implementation, but that's not the case in general. >> >IMHO imposing that as a requirement would unduly restrict the >> >compiler's freedom to optimize code. >> >> As long as it optimises at compile time, it is free to do whatever it >> wants, except at a few locations that hold catch statements. > >That's not correct. If you want to preserve the nice properties of >pure functional programming, then optimization would be inhibited in any >code which might be called from a catch statement. a) I don't see why (see below). b) usually, one does not call a lot of code in exception handlers. >Since it is common >practice to put an exception handler at the very top level, this would >typically mean the entire program. a) I have to disagree. It would not be uncommon to have exception handlers deeper down, provided that the language does not make it almost impossible. b) Most code does NOT get called by the handler. Or are you referring to the guarded code? >If you don't inhibit such optimizations, then you would end up in the >situation where applying simple and obvious transformations such as >replacing a variable with its definition might change the program's >behaviour. Suppose I have: Start = program catch DivideByZero = abort "divide by zero" catch StackOverFlow = abort "stack overflow" catch ... Yes, I agree that it depends on the optimisations which exception will get thrown first. But I don't see why the "program" expression cannot be optimised. All functions without catch statements can be optimised as usual. Optimisations just cannot obviously go "through" (a few) functions with a handler. >> And then, there is still the possibility to enforce catch statements >> to always deliver the same constant expression on any exception. > >Not if you permit statements that might not halt. Otherwise the compiler >in general still can't reorder code, such as the evaluation of x and y in >"x + y", because "catch(1/0 + loop)" will terminate whereas >"catch(loop + 1/0)" will loop. > >Automatic termination analysis is still not yet good enough to want to >rely on it -- after all, this is the classic halting problem! Well, perhaps we are not thinking/talking about the same thing. I meant to say that the _handler_ always delivers the same expression for the same set of function arguments, independed of the actual exception it caught (i.e. independent of optimisation). In that way, it becomes impossible to detect from the outside of the function (Start above) what exception was throw. This is trivially so, if the handler does not get the exception value as an argument. It would be sad however, to loose the exception information, so I consider this to be a last resort. >-- >Fergus Henderson | "I have always known that the pursuit >The University of Melbourne | of excellence is a lethal habit" >WWW: | -- the last words of T. S. Garp. From fjh@cs.mu.OZ.AU Tue, 16 Dec 2003 03:56:03 +1100 Date: Tue, 16 Dec 2003 03:56:03 +1100 From: Fergus Henderson fjh@cs.mu.OZ.AU Subject: [clean-list] Clean in the Real World On 15-Dec-2003, Marco Kesseler wrote: > Fergus wrote > >On 15-Dec-2003, Marco Kesseler wrote: > >> > >> As long as it optimises at compile time, it is free to do whatever it > >> wants, except at a few locations that hold catch statements. > > > >That's not correct. If you want to preserve the nice properties of > >pure functional programming, then optimization would be inhibited in any > >code which might be called from a catch statement. Since it is common > >practice to put an exception handler at the very top level, this would > >typically mean the entire program. > > a) I have to disagree. It would not be uncommon to have exception > handlers deeper down, provided that the language does not make it > almost impossible. It's common to have exception handlers deeper down, but usually there will also be a top-level handler to catch any unexpected exceptions. > b) Most code does NOT get called by the handler. Or are you referring > to the guarded code? Yes, I'm referring to the guarded code. > >If you don't inhibit such optimizations, then you would end up in the > >situation where applying simple and obvious transformations such as > >replacing a variable with its definition might change the program's > >behaviour. > > Suppose I have: > > Start > = program > catch DivideByZero = abort "divide by zero" > catch StackOverFlow = abort "stack overflow" > catch ... In your example code above, you didn't give a precise syntax or semantics for the new "catch" construct... am I right to presume that you mean that this construct could be used in contexts where there is no World passing or nondeterminism monad? For example, could it be used in foo :: Int foo = bar catch DivideByZero = baz ? If so, then either (a) I won't be able to safely apply equational reasoning to my programs any more, or (b) compiler optimizations will be inhibited for any code which might be guarded by a catch. > Yes, I agree that it depends on the optimisations which exception > will get thrown first. Right. And that in turn means that the value of "Start" (or "foo") may differ depending on what optimizations are applied. Which may depend on seemingly unimportant details of the implementation of "program" (or "bar"). Unless code which catches exceptions is restricted to a nondeterminism monad or equivalent, referential transparency will be violated. Programmers will no longer be able to safely apply equational reasoning to transform the definition of "bar", because such transformations might change the value of "foo". > But I don't see why the "program" expression cannot be optimised. If you're willing to violate referentially transparency, you can certainly perform such optimizations. But then you lose most of the nice properties of pure functional programming, like equational reasoning. > >> And then, there is still the possibility to enforce catch statements > >> to always deliver the same constant expression on any exception. > > > >Not if you permit statements that might not halt. Otherwise the compiler > >in general still can't reorder code, such as the evaluation of x and y in > >"x + y", because "catch(1/0 + loop)" will terminate whereas > >"catch(loop + 1/0)" will loop. > > > >Automatic termination analysis is still not yet good enough to want to > >rely on it -- after all, this is the classic halting problem! > > Well, perhaps we are not thinking/talking about the same thing. I > meant to say that the _handler_ always delivers the same expression > for the same set of function arguments, independed of the actual > exception it caught (i.e. independent of optimisation). I understood that. But maybe you didn't understand my reply, which I admittedly did not explain very clearly. The problem is that as well as exceptions, there is also nontermination, and the semantics for "catch" needs to deal with them both. > In that way, it becomes impossible to detect from the outside of the > function (Start above) what exception was throw. This is trivially so, > if the handler does not get the exception value as an argument. You can't detect what exception was thrown, but "catch" can still be used to distinguish the order of evaluation, because you can detect the difference between throwing an exception and going into an infinite loop. If we have foo :: Int foo = bar catch _ = baz bar = (1/0) + loop and the compiler evaluates the addition left-to-right, then "bar" will throw a DivideByZero exception, and so "foo" will return "baz", but if the compiler evaluates the addition right-to-left, then neither "foo" nor "bar" will terminate. -- Fergus Henderson | "I have always known that the pursuit The University of Melbourne | of excellence is a lethal habit" WWW: | -- the last words of T. S. Garp. From greenrd@greenrd.org Mon, 15 Dec 2003 21:05:04 +0000 Date: Mon, 15 Dec 2003 21:05:04 +0000 From: Robin Green greenrd@greenrd.org Subject: [clean-list] Clean in the Real World On Mon, Dec 15, 2003 at 03:02:25PM +0100, Marco Kesseler wrote: > Apart from that, the same non-deterministic effects will occur in the > Monadic solution. The fact that this is theoretically allowed may not > help the average programmer in reasoning about his program. > > (which does _not_ imply that I am against soundness) > > And then, there is still the possibility to enforce catch statements > to always deliver the same constant expression on any exception. (Disclaimer: I haven't read the Imprecise Exceptions paper.) I think I understand why one might want to put exception handling in a monad. Because, to preserve equational reasoning, with the existence of non-deterministic exceptions such as e.g. InputOutputException (disk full, network disconnected, etc.), it is not even enough to say that a catch statement must not expose anything about the exception that has occurred. It must _also_ be able to reproduce the same value, if it it returns a value, as the guarded expression would have if it _could_ have returned! This implies that if a non-deterministic exception can possibly be thrown from a guarded expression, there are _only_ three possible "action outcomes" a handler can decide between: 1. Retry evaluation 2. Abort program entirely 3. Throw an exception (possibly the same one that it has caught, possibly not) (Retry, Abort, or Throw) Right? It cannot return a value other than through (1) since this would violate equational reasoning. I think that is clear. While Bertrand Meyer (not a functional-ist per se, but an advocate of rigorous exception handling) might be happy with this tortuous arrangement, I personally am not. It seems too limiting (what about user interaction?) So it seems sensible to put _some_ exception handling in a non-referentially-transparent part of the system, which in the context of pure languages like Clean implies either (as a prior post suggested) in a separate process, or in a monad. I don't think uniqueness typing really works for this application, because of cases in which exceptions could occur all over the place, and therefore you'd have to pass around an exception-recording "World" state _everywhere_ - which rather changes the semantics of your program, as I previously argued. Of course, if you want to sensibly deal with out of memory exceptions or such things, they certainly can occur all over the place, in general. -- Robin "it's FREE and we get the ability to modify the source code ourselves, something that is extremely dangerous to do, was discredited decades ago..." - Howard Strauss writing in Syllabus magazine http://www.syllabus.com/article.asp?id=8460 From m.wittebrood@mailbox.kun.nl Mon, 15 Dec 2003 23:49:53 +0100 Date: Mon, 15 Dec 2003 23:49:53 +0100 From: Marco Kesseler m.wittebrood@mailbox.kun.nl Subject: [clean-list] Clean in the Real World Fergus wrote: >On 15-Dec-2003, Marco Kesseler wrote: >> Fergus wrote >> >On 15-Dec-2003, Marco Kesseler wrote: >> >If you don't inhibit such optimizations, then you would end up in the >> >situation where applying simple and obvious transformations such as >> >replacing a variable with its definition might change the program's >> >behaviour. >> >> Suppose I have: >> >> Start >> = program >> catch DivideByZero = abort "divide by zero" >> catch StackOverFlow = abort "stack overflow" >> catch ... > >In your example code above, you didn't give a precise syntax or semantics >for the new "catch" construct... I am not really in a position to do such things in any sensible way (This is not my job). >am I right to presume that you mean >that this construct could be used in contexts where there is no World >passing or nondeterminism monad? Yes. >For example, could it be used in > > foo :: Int > foo > = bar > catch DivideByZero = baz Yes. >If so, then either (a) I won't be able to safely apply equational reasoning >to my programs any more, or (b) compiler optimizations will be inhibited >for any code which might be guarded by a catch. You will: (a) be able to apply equational reasoning within your program, in the sense that if an exception occurs within foo, it will always deliver the same result (baz), because it will always throw the same exception, by virtue of the compiler generating a fixed evaluation order for bar. If no exception occurs, everything will be as usual and bar gets returned (but also see below). (b) have compiler optimisations both in bar and baz, as it does not matter which exception gets thrown in bar, as long as it is the same one each time within a single program. The one thing that is not possible, in terms of optimisation, is to simply replace occurences of foo by bar. You cannot, because foo does not just equal bar, and there is no notation to attach the handler to a loose bar. And you should not because then the compiler would have to ensure that each of these occurences of bar employs the same evaluation order. >> Yes, I agree that it depends on the optimisations which exception >> will get thrown first. > >Right. And that in turn means that the value of "Start" (or "foo") may >differ depending on what optimizations are applied. Which may depend >on seemingly unimportant details of the implementation of "program" >(or "bar"). Yes, this is actually more reproducable than via a nondeterminism monad. >Unless code which catches exceptions is restricted to a nondeterminism >monad or equivalent, referential transparency will be violated. >Programmers will no longer be able to safely apply equational reasoning >to transform the definition of "bar", because such transformations >might change the value of "foo". Programmers can use whatever equational reasoning they want to transform the definiton of bar. Within bar there is _nothing_ that reminds the programmer of exceptions. And if they do not make mistakes, the meaning of bar will stay exactly the same. Now if you recompile your program after transforming it, AND the evaluation of bar leads to an exception AND the transformation leads to a _different_ exception than before, then yes, foo _may_ deliver a different value than before. However, it will do so _consistently_ in your program, and you can honestly say that foo == foo. The latter is something you _cannot_ say if you use the Monadic approach, were a "deus ex machina" tells you which exception value to take each time you refer to getException. Does it really matter whether this exception happens because the strictness analyser spent more time analysing, whether you changed an optimisation option, whether you made a mistake, or whether it happened because you reversed two arguments? The important thing is, that if foo was previously able to transform all possible exceptions into sensible values, it should also be able to do it now, after the change. >> But I don't see why the "program" expression cannot be optimised. > >If you're willing to violate referentially transparency, >you can certainly perform such optimizations. But then you lose >most of the nice properties of pure functional programming, like >equational reasoning. I am not willing to violate referential transparency (just yet). If I were, this discussion would not have become this long. Speaking of referential transparency: what is so referentially transparent about the Monadic approach: getException x >>= (\v1 -> getException x >>= (\v2 -> return (v1 == v2) Why question this? For the simple fact that "getException x" does not deliver the same value each time. [snipping in previous quote] >> >> Well, perhaps we are not thinking/talking about the same thing. I >> meant to say that the _handler_ always delivers the same expression >> for the same set of function arguments, independed of the actual >> exception it caught (i.e. independent of optimisation). > >I understood that. But maybe you didn't understand my reply, which I >admittedly did not explain very clearly. The problem is that as well >as exceptions, there is also nontermination, and the semantics for >"catch" needs to deal with them both. > >> In that way, it becomes impossible to detect from the outside of the >> function (Start above) what exception was throw. This is trivially so, >> if the handler does not get the exception value as an argument. > >You can't detect what exception was thrown, but "catch" can still be >used to distinguish the order of evaluation, because you can detect the >difference between throwing an exception and going into an infinite loop. >If we have > > foo :: Int > foo > = bar > catch _ = baz > > bar = (1/0) + loop > >and the compiler evaluates the addition left-to-right, then "bar" >will throw a DivideByZero exception, and so "foo" will return "baz", >but if the compiler evaluates the addition right-to-left, then neither >"foo" nor "bar" will terminate. Well, luckily our programs only have to be referentially transparent if they terminate. In practice, this is a non-issue. Marco (Variation on a theme: the proof of the program is in the programming) >-- >Fergus Henderson | "I have always known that the pursuit >The University of Melbourne | of excellence is a lethal habit" >WWW: | -- the last words of T. S. Garp. > > >_______________________________________________ >clean-list mailing list >clean-list@cs.kun.nl >http://www.cs.kun.nl/mailman/listinfo/clean-list From m.wittebrood@mailbox.kun.nl Tue, 16 Dec 2003 00:23:07 +0100 Date: Tue, 16 Dec 2003 00:23:07 +0100 From: Marco Kesseler m.wittebrood@mailbox.kun.nl Subject: [clean-list] Clean in the Real World >On Mon, Dec 15, 2003 at 03:02:25PM +0100, Marco Kesseler wrote: >> Apart from that, the same non-deterministic effects will occur in the >> Monadic solution. The fact that this is theoretically allowed may not >> help the average programmer in reasoning about his program. >> >> (which does _not_ imply that I am against soundness) >> >> And then, there is still the possibility to enforce catch statements >> to always deliver the same constant expression on any exception. > >(Disclaimer: I haven't read the Imprecise Exceptions paper.) >I think I understand why one might want to put exception handling in >a monad. Because, to preserve equational reasoning, with the existence >of non-deterministic exceptions such as e.g. InputOutputException (disk >full, network disconnected, etc.), it is not even >enough to say that a catch statement must not expose >anything about the exception that has occurred. It must _also_ >be able to reproduce the same value, if it it returns a value, >as the guarded expression would have if it _could_ have returned! The imprecise exception paper distinguises three types of exceptions: * disaster-type, like dividision by zero. * alternative return, like when you throw an exception to indicate that some search has failed. * asynchronous exceptions, like "ctrl-C", or the I/O exceptions you mention above. The whole discussion until now does not have to do with the asychronous exceptions. These are - by their very nature - related to I/O and thus indeed belong to either I/O Monad or a unique "World" state (well, in my view anyway). The other two types - i.e. the synchronous ones - have the property that they can be "replayed". They will happen again, if you evaluate the same expression in exactly the same way. The problem now is, that a compiler (for a functional language) does not always have to evaluate the same expression in the same way. So depending on the evaluation order that the compiler chooses, the result of catching an exception may differ if you write down the same expression twice. To come back to your remark: in case of a synchronous exception, there is no "real" return value, and there never will be, as the exception will always happen. So the catch statement is free to choose whatever value it wants. >This implies that if a non-deterministic exception can possibly be >thrown from a guarded expression, there are _only_ three possible >"action outcomes" a handler can decide between: > >1. Retry evaluation >2. Abort program entirely >3. Throw an exception (possibly the same one that it has caught, >possibly not) > >(Retry, Abort, or Throw) > >Right? It cannot return a value other than through (1) since this would >violate equational reasoning. I think that is clear. > >While Bertrand Meyer (not a functional-ist per se, but an advocate >of rigorous >exception handling) might be happy with this tortuous arrangement, I >personally am not. It seems too limiting (what about user interaction?) >So it seems sensible to put _some_ exception handling in a >non-referentially-transparent part of the system, which in the context >of pure languages like Clean implies either (as a prior >post suggested) in a separate process, or in a monad. I don't think >uniqueness typing really works for this application, because of cases >in which exceptions could occur all over the place, and therefore you'd >have to pass around an exception-recording "World" state _everywhere_ - >which rather changes the semantics of your program, as I previously argued. This "trap" is basically the same for Monads, which is why I really want to avoid such a solution. >Of course, if you want to sensibly deal with out of memory exceptions or >such things, they certainly can occur all over the place, in general. Out-of-memory exceptions, and stack overflows are actually not of the "replay" kind, so they can certainly not be handled by the solution that I proposed. It is also not clear (to me) how they should be handled if they were part of the IO Monad or the Unique World: (a) you need some memory to actually execute a handler and (b) you cannot manipulate the heap or the stack from within Clean or Haskell. Marco >-- >Robin > >"it's FREE and we get the ability to modify the source code ourselves, >something that is extremely dangerous to do, was discredited decades ago..." > - Howard Strauss writing in Syllabus magazine > http://www.syllabus.com/article.asp?id=8460 > From simonmar@microsoft.com Tue, 16 Dec 2003 09:45:51 -0000 Date: Tue, 16 Dec 2003 09:45:51 -0000 From: Simon Marlow simonmar@microsoft.com Subject: [clean-list] Clean in the Real World > You will: > (a) be able to apply equational reasoning within your program, in the > sense that if an exception occurs within foo, it will always deliver > the same result (baz), because it will always throw the same > exception, by virtue of the compiler generating a fixed evaluation > order for bar. If no exception occurs, everything will be as usual > and bar gets returned (but also see below). > (b) have compiler optimisations both in bar and baz, as it does not > matter which exception gets thrown in bar, as long as it is the same > one each time within a single program. I think you've missed the point here. Yes, you can still use equational reasoning in your system, but there are now fewer equations which are valid. For example, previously I had the equation a + b = b + a but now this doesn't apply. If you don't put the exception catcher in a nondeterminism monad (or similar), then your language ends up with fewer equational properties. This is precisely what we went to great lengths to avoid in Haskell. Cheers, Simon From m.wittebrood@mailbox.kun.nl Tue, 16 Dec 2003 21:04:13 +0100 Date: Tue, 16 Dec 2003 21:04:13 +0100 From: Marco Kesseler m.wittebrood@mailbox.kun.nl Subject: [clean-list] Clean in the Real World > >> You will: >> (a) be able to apply equational reasoning within your program, in the >> sense that if an exception occurs within foo, it will always deliver >> the same result (baz), because it will always throw the same >> exception, by virtue of the compiler generating a fixed evaluation >> order for bar. If no exception occurs, everything will be as usual >> and bar gets returned (but also see below). >> (b) have compiler optimisations both in bar and baz, as it does not >> matter which exception gets thrown in bar, as long as it is the same >> one each time within a single program. > >I think you've missed the point here. Yes, you can still use equational >reasoning in your system, but there are now fewer equations which are >valid. For example, previously I had the equation > > a + b = b + a > >but now this doesn't apply. If you don't put the exception catcher in a >nondeterminism monad (or similar), then your language ends up with fewer >equational properties. This is precisely what we went to great lengths >to avoid in Haskell. Commutativity is NOT a property of all functions. '-' is not commutative. '+' is not commutative because it uses the '+' symbol. Commutativity can only be established after inspecting the function definition. Say that '+' has been defined like: (+) a b = add a b. 'add' is a primitive operation that is strict in its arguments. It first evaluates arg 1, then evaluates arg 2, and then adds them. All of these steps may throw exceptions. Kind of a real world thing (for all of you who wonder about this thread's subject). '+' remains commutative here: no exception thrown inside (a + b) will _ever_ influence the value of (a + b), as all exceptions will just pass up to higher levels. These higher levels will _not_ be able to establish the value of (a + b). They only know that some exception was thrown while evaluating it. Now suppose that we add a general catch to the '+' definition. Just for the sake of the argument, because this is probably pointless for a function like '+'. (+) a b = add a b catch _ = NotANumber /* map any exception to this special value */ Now, '+' is _still_ commutative, because any exception maps to the same value. Either everything goes well, and the value of (a + b) gets computed, or something goes wrong, and NotANumber gets returned. This happens for (a + b) and (b + a) alike. We take the definition of (+) one step further: (+) a b = add a b catch DivideByZero = NotANumber /* the only exception that we handle */ catch e = throw e /* we pass all other exceptions to higher levels */ We have now entered the twilight zone. In most cases, '+' will behave the same as in the case were it has no handlers at all. Only if a division by zero gets thrown first it will deliver NotANumber. This means that for some a and b, (a + b) may deliver NotAnumber, while (b + a) may not deliver any value at all, because another exception got thrown first. Is '+' still commutative? I don't know. For the values I can check it is, but for the others? Let's assume it is not, because I am in a good mood. So, let's REALLY break commutativity! (+) a b = add a b catch DivideByZero = NotANumber catch _ = AVeryBigValue /* Sad */ Okay, so now we have defined a non-commutative '+'. Do we need exceptions for that? No. If I want, I can define a non-commutative '+' in Clean today. How about: (+) a b = a - b. I may well have missed the point, but I somehow doubt that this was it. regards, Marco >_______________________________________________ >clean-list mailing list >clean-list@cs.kun.nl >http://www.cs.kun.nl/mailman/listinfo/clean-list From fjh@cs.mu.OZ.AU Wed, 17 Dec 2003 10:02:31 +1100 Date: Wed, 17 Dec 2003 10:02:31 +1100 From: Fergus Henderson fjh@cs.mu.OZ.AU Subject: [clean-list] Clean in the Real World On 16-Dec-2003, Marco Kesseler wrote: > [Simon Marlow wrote:] > >I think you've missed the point here. Yes, you can still use equational > >reasoning in your system, but there are now fewer equations which are > >valid. For example, previously I had the equation > > > > a + b = b + a > > > >but now this doesn't apply. If you don't put the exception catcher in a > >nondeterminism monad (or similar), then your language ends up with fewer > >equational properties. This is precisely what we went to great lengths > >to avoid in Haskell. > > Commutativity is NOT a property of all functions. '-' is not > commutative. '+' is not commutative because it uses the '+' symbol. > Commutativity can only be established after inspecting the function > definition. Yes. But in mathematics, "+" is normally commutative. It would be nice if that was true of our functional programming languages too. > Say that '+' has been defined like: > > (+) a b = add a b. > > 'add' is a primitive operation that is strict in its arguments. It > first evaluates arg 1, then evaluates arg 2, and then adds them. All > of these steps may throw exceptions. Kind of a real world thing (for > all of you who wonder about this thread's subject). > > '+' remains commutative here: No, it doesn't. It is commutative for arguments that do not throw exceptions, or in the case where only one argument throws an exception, or where both arguments throw the same exception. But if both arguments throw distinct exceptions, then the result of "a + b" will be different from "b + a", because it will throw a different exception. I suppose you could call it "semi-commutative" or something like that, in the sense that it is commutative for non-exceptional arguments. But we are also interested in cases where exceptions are thrown or where the program fails to terminate. > no exception thrown inside (a + b) will > _ever_ influence the value of (a + b), as all exceptions will just > pass up to higher levels. These higher levels will _not_ be able to > establish the value of (a + b). They only know that some exception > was thrown while evaluating it. Once you introduce exceptions, semantically the value of (a + b) is a discriminated union of either a number or an exception. Higher levels can establish which exception was thrown. > Now suppose that we add a general catch to the '+' definition. Just > for the sake of the argument, because this is probably pointless for > a function like '+'. > > (+) a b > = add a b > catch _ = NotANumber /* map any exception to this special value */ > > Now, '+' is _still_ commutative, because any exception maps to the > same value. This version of "+" is commutative (but not "_still_" commutative, since the original one wasn't commutative!). However, it doesn't propagate any exceptions. So it doesn't solve the problem of introducing exceptions while retaining equational reasoning. > We take the definition of (+) one step further: > > (+) a b > = add a b > catch DivideByZero = NotANumber /* the only exception that we > handle */ > catch e = throw e /* we pass all other exceptions to higher > levels */ This one is not commutative. > So, let's REALLY break commutativity! > > (+) a b > = add a b > catch DivideByZero = NotANumber > catch _ = AVeryBigValue /* Sad */ Yes, this one is not commutative either. > Okay, so now we have defined a non-commutative '+'. Do we need > exceptions for that? No. If I want, I can define a non-commutative > '+' in Clean today. We're not trying to define a non-commutative '+'. We're trying to define a commutative one! The point is that today in Clean one can easily define a commutative '+'. If we introduce exceptions and allow catch only in a nondeterminism monad or equivalent, then this will still be the case. But if we introduce exceptions in the way that you have proposed, it won't be possible to define a commutative '+' without explicitly catching exceptions (as in your second example above), and we don't want to do that, since the whole point of introducing exceptions was to have them automatically propagate through operations like '+'. -- Fergus Henderson | "I have always known that the pursuit The University of Melbourne | of excellence is a lethal habit" WWW: | -- the last words of T. S. Garp. From fjh@cs.mu.OZ.AU Wed, 17 Dec 2003 11:32:57 +1100 Date: Wed, 17 Dec 2003 11:32:57 +1100 From: Fergus Henderson fjh@cs.mu.OZ.AU Subject: [clean-list] Clean in the Real World On 15-Dec-2003, Marco Kesseler wrote: > Fergus wrote: > >am I right to presume that you mean > >that this construct could be used in contexts where there is no World > >passing or nondeterminism monad? ... > >For example, could it be used in > > > > foo :: Int > > foo > > = bar > > catch DivideByZero = baz > > Yes. > >If so, then either (a) I won't be able to safely apply equational reasoning > >to my programs any more, or (b) compiler optimizations will be inhibited > >for any code which might be guarded by a catch. > > You will: > (a) be able to apply equational reasoning within your program, in the > sense that if an exception occurs within foo, it will always deliver > the same result (baz), because it will always throw the same > exception, by virtue of the compiler generating a fixed evaluation > order for bar. Suppose the expression "a + b" occurs in the definition of "bar". I can't safely apply equational reasoning to replace this with "b + a", because that might change the value returned from foo. Or, if we consider a slightly different example, where foo takes a parameter x, foo :: Int -> Int foo x = bar x catch DivideByZero = baz x you may have "foo (a + b)" being different than "foo (b + a)". > (b) have compiler optimisations both in bar and baz, as it does not > matter which exception gets thrown in bar, as long as it is the same > one each time within a single program. > > The one thing that is not possible, in terms of optimisation, is to > simply replace occurences of foo by bar. You cannot, because foo does > not just equal bar, and there is no notation to attach the handler to > a loose bar. And you should not because then the compiler would have > to ensure that each of these occurences of bar employs the same > evaluation order. That's not the only thing which is not possible, in general. You also can't easily specialize occurrences of foo. That's not important for that original example, but consider another slight variation: foo :: Int -> Int -> Int foo f = bar f catch DivideByZero = baz f If "bar" calls "f" often, and there is a call to "foo (\ x y -> x + y)", then it may be very important for performance to specialize both "foo" and "bar", so that the calls to f can be inlined to a single cheap add instruction rather than the expensive sequence of instructions needed for a call to an unknown higher-order function term. Well, I suppose the compiler could do the specialization, provided that it was done _after_ any optimizations that change the order of evaluation. But normally the compiler should do such specializations first, and then apply all the other optimizations, such as inlining, constant propagation, etc., so that the specialized code can be simplified. > I am not willing to violate referential transparency (just yet). If I > were, this discussion would not have become this long. Speaking of > referential transparency: what is so referentially transparent about > the Monadic approach: > > getException x >>= (\v1 -> > getException x >>= (\v2 -> > return (v1 == v2) > > Why question this? For the simple fact that "getException x" does not > deliver the same value each time. "getException x" always evaluates to the same value, an IO action. When you talk about "delivering" a value, you mean applying this action to some particular world state to get a concrete value rather than an IO action. If you apply the action to two different states then naturally you may get different values delivered. That is the case in your example above. > >If we have > > > > foo :: Int > > foo > > = bar > > catch _ = baz > > > > bar = (1/0) + loop > > > >and the compiler evaluates the addition left-to-right, then "bar" > >will throw a DivideByZero exception, and so "foo" will return "baz", > >but if the compiler evaluates the addition right-to-left, then neither > >"foo" nor "bar" will terminate. > > Well, luckily our programs only have to be referentially transparent > if they terminate. > > In practice, this is a non-issue. If the compiler transforms a terminating program into a non-terminating one, that is usually considered to be a rather serious issue :) -- Fergus Henderson | "I have always known that the pursuit The University of Melbourne | of excellence is a lethal habit" WWW: | -- the last words of T. S. Garp. From zweije@xs4all.nl Wed, 17 Dec 2003 09:28:05 +0100 Date: Wed, 17 Dec 2003 09:28:05 +0100 From: Vincent Zweije zweije@xs4all.nl Subject: [clean-list] Clean in the Real World On Wed, Dec 17, 2003 at 11:32:57AM +1100, Fergus Henderson wrote: || On 15-Dec-2003, Marco Kesseler wrote: || > Well, luckily our programs only have to be referentially transparent || > if they terminate. || > || > In practice, this is a non-issue. || || If the compiler transforms a terminating program into a non-terminating || one, that is usually considered to be a rather serious issue :) The reverse is also a serious issue, because your program might suddenly no longer terminate if you switch compiler or compiler options. You don't want that. Vincent. From karczma@info.unicaen.fr Wed, 17 Dec 2003 10:18:29 +0100 Date: Wed, 17 Dec 2003 10:18:29 +0100 From: Jerzy Karczmarczuk karczma@info.unicaen.fr Subject: [clean-list] type reporting This is a multi-part message in MIME format. --------------060006040209030503020608 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit Maestros, Some simple questions concerning the behaviour of your type reporter. It is very nice to have a readable type report, which can then be copied/pasted to the definition module, etc. But quite a time ago I discovered that it writes sometimes some types which are illegal, which are not accepted by the compiler itself. So, it was most probably some cosmetic error in writing down the type. That error has probably been corrected, I can't track it anyway. But I have others. I attach the full program. It contains a function fractnoise which has an internal one: 'midpoint'. It begins like that: fractnoise kappa nstages seed = fr seed where fctr = 0.5^kappa fr seed # (l,seed) = midpoint [#0.0,0.0] 1.0 nstages seed = l ++| fr seed midpoint l _ 0 seed = (l,seed) midpoint (xs=:[#x0:xq]) amp n seed #! (l1,seed) = mdsp xq xs [#x0] amp seed ............... and the type inferrer reports: midpoint :: Real u:[#Real] Real !Int Int -> (v:[#Real],Int), [u <= v] For goodness' sake, the function midpoint accepts 4 parameters, not 5. What the first Real is doing there? The first argument is a list. ************************************************************* Since I overload lists (in fact I use [#Real] only), the typechecker generates some internal objects, in particular: map_ :: (u:a -> v:b) !w:(c u:a) -> x:(d v:b) | List; c a & List; d b, [w <= u,x <= v] Why this semicolon after List? It is not accepted by the compiler. Also, another function: readWav fname world # (bool,file,world) = fopen fname FReadData world .................... produces readWav :: {#.Char} *a -> *(.{#Char},*a) | FileSystem; a Again a spurious semicolon. Thank you. Jerzy Karczmarczuk --------------060006040209030503020608 Content-Type: text/plain; name="purebug.icl" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="purebug.icl" module purebug import StdEnv import StdStrictLists, StdOverloadedList class (*>) infixr 7 t :: !Real (t Real) -> (t Real) instance *> [#] where (*>) x l = Map (\s -> x*s) l ZipWith op l1 l2 :== ZipWith l1 l2 where ZipWith [|a:as] [|b:bs] = [|(op a b) : ZipWith as bs] ZipWith as bs = [|] instance + [#Real] where (+) l1 l2 = ZipWith (+) l1 l2 instance - [#Real] where (-) l1 l2 = ZipWith (-) l1 l2 rand1_s seed # seed = 599479 + seed*25781083 = (toReal seed/2147483648.0,seed) fractnoise kappa nstages seed = fr seed where fctr = 0.5^kappa fr seed # (l,seed) = midpoint [#0.0,0.0] 1.0 nstages seed = l ++| fr seed midpoint l _ 0 seed = (l,seed) midpoint (xs=:[#x0:xq]) amp n seed #! (l1,seed) = mdsp xq xs [#x0] amp seed = midpoint l1 (amp*fctr) (n-1) seed mdsp [#x1:xq] [#y0:yq] tmp a seed #! (r,seed) = rand1_s seed #! z = 0.5*(x1+y0) + r*a = mdsp xq yq [#x1 : z : tmp] a seed mdsp _ _ tmp _ seed = (tmp,seed) readWav :: {#.Char} *a -> *(.{#Char},*a) | FileSystem; a readWav fname world # (bool,file,world) = fopen fname FReadData world | not bool = abort "Cannot open Wav file" # (hrif,file) = freads file 4 | hrif <> "RIFF" = abort "Not a RIFF file" # (tbool,flen,file) = freadi file # (hwav,file) = freads file 4 | hwav <> "WAVE" = abort "Not a WAVE file" # totlen = flen+8 # (ok2,file) = fseek file 0 FSeekSet # (data,file) = freads file totlen # (cbool,world) = fclose file world = (data,world) Start = "OK" --------------060006040209030503020608-- From ronny@cs.kun.nl Wed, 17 Dec 2003 10:43:20 +0100 Date: Wed, 17 Dec 2003 10:43:20 +0100 From: Ronny Wichers Schreur ronny@cs.kun.nl Subject: [clean-list] type reporting Jerzy Karczmarczuk writes (to the Clean Discussion list): > fractnoise kappa nstages seed = fr seed where > fctr = 0.5^kappa > fr seed > # (l,seed) = midpoint [#0.0,0.0] 1.0 nstages seed > = l ++| fr seed > midpoint l _ 0 seed = (l,seed) > midpoint (xs=:[#x0:xq]) amp n seed > #! (l1,seed) = mdsp xq xs [#x0] amp seed > ............... > > and the type inferrer reports: > > midpoint :: Real u:[#Real] Real !Int Int > -> (v:[#Real],Int), [u <= v] > > For goodness' sake, the function midpoint accepts 4 > parameters, not 5. What the first Real is doing there? > The first argument is a list. The function midpoint uses fctr. The reported type includes this lifted argument. > map_ :: (u:a -> v:b) !w:(c u:a) -> x:(d v:b) > | List; c a & List; d b, [w <= u,x <= v] > > Why this semicolon after List? It is not accepted by > the compiler. That's a bug. In Clean classes and (record) types are in different name spaces, but during the translation a dictionary record type is associated with each type. The semicolon is there to prevent a name clash, but we forgot to remove the semi- colon in the "List all types" output. Cheers, Ronny Wichers Schreur From m.wittebrood@mailbox.kun.nl Wed, 17 Dec 2003 15:09:48 +0100 Date: Wed, 17 Dec 2003 15:09:48 +0100 From: Marco Kesseler m.wittebrood@mailbox.kun.nl Subject: [clean-list] Clean in the Real World Fergus wrote: >On 16-Dec-2003, Marco Kesseler wrote: [snip] >> Say that '+' has been defined like: >> >> (+) a b = add a b. >> >> 'add' is a primitive operation that is strict in its arguments. It >> first evaluates arg 1, then evaluates arg 2, and then adds them. All >> of these steps may throw exceptions. Kind of a real world thing (for >> all of you who wonder about this thread's subject). >> >> '+' remains commutative here: > >No, it doesn't. > >It is commutative for arguments that do not throw >exceptions, or in the case where only one argument throws an exception, >or where both arguments throw the same exception. But if both arguments >throw distinct exceptions, then the result of "a + b" will be different >from "b + a", because it will throw a different exception. Notwithstanding my defeat in the referential transparency issue: Yes, it does. If (a + b) throws an exception, it HAS NO RESULT. It is only in the handling function that the exception gets noticed. But that may be far, far up. And then, this handling function may start behaving non-referentially transparent by delivering a value that depends on the actual exception (which I do NOT condone). This non-deterministic value does not have anything to do with the value of (a + b). It cannot, because it does not exist. So, (a + b) _is_ commutative. If we take a look at "foo" again: foo :: Int -> Int foo x = bar x catch e = baz e The fact that foo(a + b) may not equal foo(b + a) does not have to do anything with '+' not being commutative. It has to do with 'foo' delivering a result that depends on the exception that the evaluation of "bar x" throws. This exception may also be caused by "bar" alone. It is not that easy. > [snip] >Once you introduce exceptions, semantically the value of (a + b) is >a discriminated union of either a number or an exception. Higher >levels can establish which exception was thrown. This alternative value comes only into play AFTER you catch the exception. If I do not catch any exceptions at all in my program, ultimately the system will transform them into an "abort", like the ones that Clean generates today. Now we could argue whether this "abort" is "the value of the program" as dictated by lambda calculus, but the point is: as my program did not catch the exception, the exception did not become an alternative value of any expression in my program. If you do not catch the exception, it simply does not exist. >> Now suppose that we add a general catch to the '+' definition. Just >> for the sake of the argument, because this is probably pointless for >> a function like '+'. >> >> (+) a b >> = add a b >> catch _ = NotANumber /* map any exception to this special value */ >> >> Now, '+' is _still_ commutative, because any exception maps to the >> same value. > >This version of "+" is commutative (but not "_still_" commutative, >since the original one wasn't commutative!). > >However, it doesn't propagate any exceptions. So it doesn't solve the >problem of introducing exceptions while retaining equational reasoning. Yes it does. The evaluation of "add a b" may introduce an exception, which then gets propagated, and handled here at the (+). If all functions that catch exceptions behave in this way, we retain equational reasoning. >> We take the definition of (+) one step further: >> >> (+) a b >> = add a b >> catch DivideByZero = NotANumber /* the only exception that we >> handle */ >> catch e = throw e /* we pass all other exceptions to higher >> levels */ > >This one is not commutative. Yes it is, because now I am less ecstatic than yesterday. For all arguments that (+) is defined for, it is commutative. It may be bad for termination to reverse the arguments though. >> So, let's REALLY break commutativity! >> >> (+) a b >> = add a b >> catch DivideByZero = NotANumber >> catch _ = AVeryBigValue /* Sad */ > >Yes, this one is not commutative either. > >> Okay, so now we have defined a non-commutative '+'. Do we need >> exceptions for that? No. If I want, I can define a non-commutative >> '+' in Clean today. > >We're not trying to define a non-commutative '+'. Yes, I was. >We're trying to define a commutative one! >The point is that today in Clean one can easily define a commutative '+'. >If we introduce exceptions and allow catch only in a nondeterminism monad >or equivalent, then this will still be the case. But if we introduce >exceptions in the way that you have proposed, it won't be possible to >define a commutative '+' without explicitly catching exceptions (as in >your second example above), and we don't want to do that, since the >whole point of introducing exceptions was to have them automatically >propagate through operations like '+'. You are right that my proposal for dealing with exceptions has a serious flaw. This flaw however, has nothing to do with the commutativity issues above. The point of explicitly defining a non-commutative '+' was merely to show that programmers can break important mathematical properties today, if they are not careful. More importantly: they can break the expectations that other programmers have of a certain symbol. So even in a referentially transparent system, foo(a + b) may not equal foo(b + a), and in practice THAT is a serious issue. Marco >-- >Fergus Henderson | "I have always known that the pursuit >The University of Melbourne | of excellence is a lethal habit" >WWW: | -- the last words of T. S. Garp.m From m.wittebrood@mailbox.kun.nl Wed, 17 Dec 2003 15:06:06 +0100 Date: Wed, 17 Dec 2003 15:06:06 +0100 From: Marco Kesseler m.wittebrood@mailbox.kun.nl Subject: [clean-list] Clean in the Real World Fergus Wrote: >On 15-Dec-2003, Marco Kesseler wrote: >> Fergus wrote: [snip] >> > foo :: Int >> > foo >> > = bar >> > catch DivideByZero = baz [snip] > >Suppose the expression "a + b" occurs in the definition of "bar". >I can't safely apply equational reasoning to replace this with "b + a", >because that might change the value returned from foo. > >Or, if we consider a slightly different example, >where foo takes a parameter x, > > foo :: Int -> Int > foo x > = bar x > catch DivideByZero = baz x > >you may have "foo (a + b)" being different than "foo (b + a)". Ah, of course: laziness. How stupid of me (and I do use it all the time, in many ways...). My apologies. Still: I REALLY do not like the Monadic solution. Sorry about that too, but that is something I cannot help. This is NOT a Monad thing in particular: I wouldn't like a "Unique World" solution either. Now there are a few things worth considering (in order of preference): * use something else than stack trimming. For _handling_ exceptions it is not that important that things go blazingly fast. However, I am afraid that things like (a) defining an order over exceptions and delivering the largest or (b) delivering the complete set of exceptions are no serious options either. At this moment, I cannot oversee what it would do to ordinary execution, but I am sure that you (Fergus) have looked into this. * Last resort solution: basically, allow only a single exception type, so that handlers cannot detect what hit them. Useful for some things, but not all. * Hurt referential transparency. Hmmmm. The only thing that is worse is: * Use another programming language. Now that I have admitted defeat, there is more (yes there is)... Please keep in mind: I am not defending lack of referential transparency below. >> (b) have compiler optimisations both in bar and baz, as it does not >> matter which exception gets thrown in bar, as long as it is the same >> one each time within a single program. >> >> The one thing that is not possible, in terms of optimisation, is to >> simply replace occurences of foo by bar. You cannot, because foo does >> not just equal bar, and there is no notation to attach the handler to >> a loose bar. And you should not because then the compiler would have >> to ensure that each of these occurences of bar employs the same >> evaluation order. > >That's not the only thing which is not possible, in general. >You also can't easily specialize occurrences of foo. >That's not important for that original example, >but consider another slight variation: > > foo :: Int -> Int -> Int > foo f > = bar f > catch DivideByZero = baz f > >If "bar" calls "f" often, and there is a call to "foo (\ x y -> x + y)", >then it may be very important for performance to specialize both >"foo" and "bar", so that the calls to f can be inlined to a single >cheap add instruction rather than the expensive sequence of instructions >needed for a call to an unknown higher-order function term. Yes, but actually I would not start being concerned about the efficiency of functions that contain exception handlers. I think the "efficiency" remarks take away the attention from the more fundamental issues. The more because it remains to be seen how often the example above appears in practice. I do agree however that the exception mechanism should not affect ordinary evaluation (badly). With this, I mean evaluation that does not in any way goes through a function with a handler. >Well, I suppose the compiler could do the specialization, provided that it >was done _after_ any optimizations that change the order of evaluation. >But normally the compiler should do such specializations first, and then >apply all the other optimizations, such as inlining, constant propagation, >etc., so that the specialized code can be simplified. > >> I am not willing to violate referential transparency (just yet). If I >> were, this discussion would not have become this long. Speaking of >> referential transparency: what is so referentially transparent about >> the Monadic approach: >> >> getException x >>= (\v1 -> >> getException x >>= (\v2 -> >> return (v1 == v2) >> >> Why question this? For the simple fact that "getException x" does not >> deliver the same value each time. > >"getException x" always evaluates to the same value, an IO action. Yes, I know. But that does not help reasoning about the value you get back. That's what I mean if I say that the proof of the program is in the programming. The syntax above is equivalent to: v1 = getException(x); v2 = getException(x); return v1 == v2; In terms of the official semantics, this may be referential transparant. In terms of what the programmer sees and experiences, it is not. THAT is something that I do not like at all. >When you talk about "delivering" a value, you mean applying this action >to some particular world state to get a concrete value rather than >an IO action. If you apply the action to two different states then >naturally you may get different values delivered. That is the case in >your example above. > >> >If we have >> > >> > foo :: Int >> > foo >> > = bar >> > catch _ = baz >> > >> > bar = (1/0) + loop >> > >> >and the compiler evaluates the addition left-to-right, then "bar" >> >will throw a DivideByZero exception, and so "foo" will return "baz", >> >but if the compiler evaluates the addition right-to-left, then neither >> >"foo" nor "bar" will terminate. >> >> Well, luckily our programs only have to be referentially transparent >> if they terminate. >> >> In practice, this is a non-issue. > >If the compiler transforms a terminating program into a non-terminating >one, that is usually considered to be a rather serious issue :) Do you call this a terminating program? That's indeed a rather serious issue :-) In the lamda calculus, there are no exceptions. Just diverging computations. If you have written such a program, it already _is_ officially non-terminating. It just happens that the system is nice enough to sometimes catch one of these and tell you. And it does not really matter whether the compiler makes it non-terminating, or some non-determism monad at runtime. It is not like the Monadic approach will spare you from non-termination. This program is a recipe for disaster. It's a deceased program. If you were a hired programmer, you'd be lucky if your boss does not find out. That's why it is a non-issue. Now I come to think of it... I could hide behind the argument that if foo(a + b) <> foo(b + a) that this was caused by a diverging computation that the system happened to catch. And, as lamda calculus does not guarantee _anything_ about diverging expressions, the exception handler can do anything it likes (call abort, for example). But that is kind of, how do you say,... a red herring? >-- >Fergus Henderson | "I have always known that the pursuit >The University of Melbourne | of excellence is a lethal habit" >WWW: | -- the last words of T. S. Garp. > > >_______________________________________________ >clean-list mailing list >clean-list@cs.kun.nl >http://www.cs.kun.nl/mailman/listinfo/clean-list From olefevre@usa.net Wed, 17 Dec 2003 18:10:10 +0100 Date: Wed, 17 Dec 2003 18:10:10 +0100 From: Olivier Lefevre olefevre@usa.net Subject: [Re: [clean-list] Clean in the Real World] > If (a + b) throws an exception, it HAS NO RESULT. Yes it has: the exception itself (at least in a language where exceptions are first-class). As Fergus said, the output type of a function (normally) returning an xxx and (possibly) throwing an eee is the discriminated union of xxx and eee. Or did I misconstrue his posting? -- O.L. From m.wittebrood@mailbox.kun.nl Wed, 17 Dec 2003 21:27:51 +0100 Date: Wed, 17 Dec 2003 21:27:51 +0100 From: Marco Kesseler m.wittebrood@mailbox.kun.nl Subject: [Re: [clean-list] Clean in the Real World] >> If (a + b) throws an exception, it HAS NO RESULT. > >Yes it has: the exception itself (at least in a language where >exceptions are first-class). As Fergus said, the output type of >a function (normally) returning an xxx and (possibly) throwing >an eee is the discriminated union of xxx and eee. > >Or did I misconstrue his posting? Unfortunately, I do not know the answer to that last question. Yes, I think that the exception itself should be a first-class value. At least, I see no good reason not to. There is no law however that says that the output type of a function should be interpreted as the union of its "actual" type and some exception type. I like the idea that the type that I write down for a function result is actually the type it has. A am not saying that it would be necessarily wrong to do so in certain systems (getException does it). It is just that I find it highly peculiar that something like "DivisionByZero" is seen as the value of an expression like (a + b), while all it says is "the computation has failed". Now when I proposed "catch" notation like: foo :: Int -> Int foo x = bar x catch e = baz e I explicitly said that cathing the exception became decoupled from the guarded expression. This was - I thought - implying that the exception does NOT get returned as part of the value of the guarded expression. If then a discussion arises w.r.t. commutativity in the "solution" that I proposed, then it seems sensible to actually reason within the boundaries of that proposal. And yes, I do think that this discussion has been very fruitful indeed. I am glad that Fergus was so persistent. regards, Marco From olefevre@usa.net Wed, 17 Dec 2003 23:15:08 +0100 Date: Wed, 17 Dec 2003 23:15:08 +0100 From: Olivier Lefevre olefevre@usa.net Subject: [Re: [Re: [clean-list] Clean in the Real World]] > There is no law however that says that the output type of a function > should be interpreted as the union of its "actual" type and some > exception type. I like the idea that the type that I write down for > a function result is actually the type it has. Something that is not clear in this discussion between you and Fergus is what you mean by "result". Do you mean the result according to the "official" semantics of a language, in which case I agree with you that a function returning an int is still that even when it can throw an exception, at least in the languages I know [*], or the result in some mental model of the program's execution in the head of the compiler writer, which might actually be expressed in a formal intermediate compilation language in which the function in question _would_ have such a discriminated union as its return type? -- O.L. [*] But note that, e.g., in Java, thrown exceptions can be part of a method signature, so in a sense they are part of its "return type". Is there any good work on how exceptions can be meshed with a type system? This discussion makes me realize that this is not obvious at all... From fjh@cs.mu.oz.au Thu, 18 Dec 2003 11:58:12 +1100 Date: Thu, 18 Dec 2003 11:58:12 +1100 From: Fergus Henderson fjh@cs.mu.oz.au Subject: [Re: [clean-list] Clean in the Real World] On 17-Dec-2003, Marco Kesseler wrote: > >> If (a + b) throws an exception, it HAS NO RESULT. > > > >Yes it has: the exception itself (at least in a language where > >exceptions are first-class). As Fergus said, the output type of > >a function (normally) returning an xxx and (possibly) throwing > >an eee is the discriminated union of xxx and eee. > > > >Or did I misconstrue his posting? No, that's what I meant. > Yes, I think that the exception itself should be a first-class value. > At least, I see no good reason not to. > > There is no law however that says that the output type of a function > should be interpreted as the union of its "actual" type and some > exception type. I like the idea that the type that I write down for a > function result is actually the type it has. You're right, that's not the only way of doing it. It is the standard way of modelling the semantics of lazy functional languages, but it is not the only possible way. Another alternative -- which we use for Mercury! -- is to not try to model exceptions in the declarative (denotational) semantics, and instead define the semantics of exception handling only in the operational semantics. Of course you do have to give some semantics for the try/catch construct in the declarative (denotational) semantics, but so long as this construct is in a nondeterminism monad or equivalent, those semantics can be loose. The denotation of the try/catch construct can give a set of possible results, which includes the possibility that an exception occurred as well as the possibility that it didn't. This approach has the advantage that the semantics of types are more obvious; for example, the boolean type has two values, not three. However, it is not without some counter-intuitive effects. Consider an expression such as "1/0 - 1/0". You still need to give a denotational semantics for each subexpression and for the expression as a whole. In Mercury's declarative semantics, this expression has the value 0, since the denotational semantics of 1/0 must be the same each time, and x - x = 0 for all x. But in the operational semantics, "1/0 - 1/0" may obviously throw an exception. The operational semantics is sound w.r.t. the declarative semantics, but not necessarily complete. For more on this, see the Haskell mailing list archives, in particular and the thread which follows, and . -- Fergus Henderson | "I have always known that the pursuit The University of Melbourne | of excellence is a lethal habit" WWW: | -- the last words of T. S. Garp. From fjh@cs.mu.oz.au Thu, 18 Dec 2003 12:16:09 +1100 Date: Thu, 18 Dec 2003 12:16:09 +1100 From: Fergus Henderson fjh@cs.mu.oz.au Subject: [clean-list] Clean in the Real World On 17-Dec-2003, Marco Kesseler wrote: > Still: I REALLY do not like the Monadic solution. Sorry about that > too, but that is something I cannot help. This is NOT a Monad thing > in particular: I wouldn't like a "Unique World" solution either. > > Now there are a few things worth considering (in order of preference): > > * use something else than stack trimming. For _handling_ exceptions > it is not that important that things go blazingly fast. However, I am > afraid that things like (a) defining an order over exceptions and > delivering the largest or (b) delivering the complete set of > exceptions are no serious options either. At this moment, I cannot > oversee what it would do to ordinary execution, but I am sure that > you (Fergus) have looked into this. I have considered it, but my first impression was that this approach would be difficult to implement and would have major negative effects on performance, so I haven't looked into it in great detail. > In terms of the official semantics, this may be referential > transparant. In terms of what the programmer sees and experiences, it > is not. THAT is something that I do not like at all. Well, the point is that all operations which might deliver different results each time are specially marked, e.g. by putting them in the IO Monad. Programmers know that operations in the IO Monad might deliver different results each time. This is the reality of programming in "pure" languages: they don't actually prevent the use of all the impure constructs of imperative languages, indeed they allow such constructs, complete with most of the drawbacks for reasoning about programs that such constructs imply. What these languages do is to just explicitly flag such constructs as being impure, by putting them in the IO Monad (or equivalent), so that programmers can safely apply equational reasoning to the parts of the program which do not use them. -- Fergus Henderson | "I have always known that the pursuit The University of Melbourne | of excellence is a lethal habit" WWW: | -- the last words of T. S. Garp. From karczma@info.unicaen.fr Thu, 18 Dec 2003 09:25:25 +0100 Date: Thu, 18 Dec 2003 09:25:25 +0100 From: Jerzy Karczmarczuk karczma@info.unicaen.fr Subject: [clean-list] Concurrent Clean, where are we? Just a simple question: What is the current state of 'concurrency' (annotations, libraries, etc.) in the wonderful world of Clean 2? I haven't seen anything dramatic recently. But I hope that the work continues. Does it? Jerzy Karczmarczuk From hugorufino@yahoo.com Thu, 18 Dec 2003 06:52:49 -0300 (ART) Date: Thu, 18 Dec 2003 06:52:49 -0300 (ART) From: =?iso-8859-1?q?Hugo=20Rufino?= hugorufino@yahoo.com Subject: [clean-list] Some examples about the Directory library --0-1325795924-1071741169=:40875 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit Hello Cleaners, I'm trying to use the functions of the Directory.dcl library, but I'm having some difficult. For example: how to use the getDirectoryContents, isHidden and getFileName functions?? Could anyone help me with some examples? Thanks a lot for any answer, -------------------------------------------------- Hugo Leonardo Pereira Rufino hugorufino@yahoo.com Uberlândia/MG - Brasil -------------------------------------------------- --------------------------------- Central anti-spam do Yahoo! Mail: com dicas, dúvidas e curiosidades! --0-1325795924-1071741169=:40875 Content-Type: text/html; charset=iso-8859-1 Content-Transfer-Encoding: 8bit
Hello Cleaners,
 
I'm trying to use the functions of the Directory.dcl library, but I'm having some difficult. For example: how to use the getDirectoryContents, isHidden and getFileName functions??  
 
Could anyone help me with some examples?
 
Thanks a lot for any answer,
 
 
 
 


--------------------------------------------------

Hugo Leonardo Pereira Rufino

hugorufino@yahoo.com

Uberlândia/MG  -  Brasil

--------------------------------------------------



Central anti-spam do Yahoo! Mail: com dicas, dúvidas e curiosidades! --0-1325795924-1071741169=:40875-- From karczma@info.unicaen.fr Thu, 18 Dec 2003 12:03:05 +0100 Date: Thu, 18 Dec 2003 12:03:05 +0100 From: Jerzy Karczmarczuk karczma@info.unicaen.fr Subject: [clean-list] Some examples about the Directory library Hugo Rufino wrote: > I'm trying to use the functions of the Directory.dcl library, but I'm > having some difficult. For example: how to use the getDirectoryContents, > isHidden and getFileName functions?? > > Could anyone help me with some examples? ======== Sorry, no answer. A question... What's wrong with the following? module dirmod import StdEnv,StdIO,Directory ff world = getDirectoryContents (AbsolutePath "D" [PathDown "\\Work"]) world Start :: *World -> ([DirEntry],*World) Start world # ((a,b),world) = ff world = (b,world) //==== Here 'a' is the error code, I *didn't want to look at*. But it caught me anyway. The program compiled and responded: (fatal error: tried to evaluate an error value returned by function getDirectoryContents). ?? Thanks. Jerzy Karczmarczuk From ronny@cs.kun.nl Thu, 18 Dec 2003 16:56:44 +0100 Date: Thu, 18 Dec 2003 16:56:44 +0100 From: Ronny Wichers Schreur ronny@cs.kun.nl Subject: [clean-list] Some examples about the Directory library Jerzy Karczmarczuk writes (to the Clean discussion list): > What's wrong with the following? > > module dirmod > import StdEnv,StdIO,Directory > > ff world = getDirectoryContents > (AbsolutePath "D" [PathDown "\\Work"]) world > > Start :: *World -> ([DirEntry],*World) > Start world > # ((a,b),world) = ff world > = (b,world) > > //==== > > > Here 'a' is the error code, I *didn't want to look at*. Shame on you! > But it caught me anyway. The program compiled and responded: > > (fatal error: tried to evaluate an error value returned by > function getDirectoryContents). Seriously: the function expects that you only inspect b if a is not an error. I don't like the design, but that's the way it is. Cheers, Ronny Wichers Schreur From arjenw@zonnet.nl Thu, 18 Dec 2003 18:52:09 +0100 Date: Thu, 18 Dec 2003 18:52:09 +0100 From: Arjen van Weelden arjenw@zonnet.nl Subject: [clean-list] Some examples about the Directory library > Jerzy Karczmarczuk writes (to the Clean discussion list): > >> What's wrong with the following? >> >> module dirmod >> import StdEnv,StdIO,Directory >> >> ff world = getDirectoryContents >> (AbsolutePath "D" [PathDown "\\Work"]) world >> >> Start :: *World -> ([DirEntry],*World) >> Start world >> # ((a,b),world) = ff world >> = (b,world) >> >> //==== >> The error is caused by the "\\" you used in "\\Work". The PathDown is introduced by this library to abstract from platform dependent directory separators. Try changing it to "Work". regards, Arjen From m.wittebrood@mailbox.kun.nl Thu, 18 Dec 2003 23:10:10 +0100 Date: Thu, 18 Dec 2003 23:10:10 +0100 From: Marco Kesseler m.wittebrood@mailbox.kun.nl Subject: [Re: [Re: [clean-list] Clean in the Real World]] >> There is no law however that says that the output type of a function >> should be interpreted as the union of its "actual" type and some >> exception type. I like the idea that the type that I write down for >> a function result is actually the type it has. > >Something that is not clear in this discussion between you and Fergus >is what you mean by "result". Do you mean the result according to >the "official" semantics of a language, in which case I agree with you >that a function returning an int is still that even when it can throw >an exception, at least in the languages I know [*], or the result in >some mental model of the program's execution in the head of the compiler >writer, which might actually be expressed in a formal intermediate >compilation language in which the function in question _would_ have >such a discriminated union as its return type? I must admit that I also have to get used to the right terminology in this area. In a pure functional language, I mean by "result" the value that a function application returns. When exceptions are involved, it may be better to more carefully talk about the "value" of an expression. In either case, I am not referring to some internal representation. >-- O.L. > >[*] But note that, e.g., in Java, thrown exceptions can be part of a >method signature, so in a sense they are part of its "return type". >Is there any good work on how exceptions can be meshed with a type >system? This discussion makes me realize that this is not obvious >at all... From karczma@info.unicaen.fr Fri, 19 Dec 2003 09:04:07 +0100 Date: Fri, 19 Dec 2003 09:04:07 +0100 From: Jerzy Karczmarczuk karczma@info.unicaen.fr Subject: [clean-list] Some examples about the Directory library Arjen van Weelden wrote: >> Jerzy Karczmarczuk writes (to the Clean discussion list): >> >>> What's wrong with the following? ... getDirectoryContents which generates a "fatal execution error" > The error is caused by the "\\" you used in "\\Work". The PathDown is > introduced by this library to abstract from platform dependent directory > separators. Try changing it to "Work". Ronny Wichers Schreurs points out that I am not allowed to read DirEntries if the reported error is an error. First, thank you very much for your help. I knew I could count on you. Then, I confess that I knew that \Work did not exist. And I confess that I read the documentation where you precise that entries are valid only if there are no errors reported. I wanted to make this suicidary experiment in order to see what's an invalid entry, since the data structures describing directories do not provide for pathologies. And I got struck by Jupiter! RWS says that he doesn't like this design. I would say more, I find it not really acceptable. Data structures which explode under your nose are against the Golden Functional Way of Life. Why not introduce ErroneousEntry case? At least then, if the user is reckless enough not to test this case, he/she will get a clean error diagnosis, and even a possible warning that the program admits a failure because not all alternatives are tested. We will survive this, of course, But, please, reconsider the design of this module. Thank you once again. I have still two questions pending, and a new one. 1. What does the compiler do when it does apparently nothing for 7 seconds before starting its dance with a 10 lines long program, and why some- times this latency time is much shorter, and sometimes not. 2. Does the Clean Respectable Team still think about the concurrency? 3. A new one, but related. Suppose I want to use Clean to process synchro- nously some input and to produce some output with the use of timers, working with small chunks. I would need to collect the garbage incremen- tally in order to avoid pausing. Will it ever be possible, according to the current vision of Clean authors? From fzuurbie@inter.nl.net Fri, 19 Dec 2003 12:28:44 UT Date: Fri, 19 Dec 2003 12:28:44 UT From: fzuurbie@inter.nl.net fzuurbie@inter.nl.net Subject: [clean-list] Some examples about the Directory library This is a multi-part message in MIME format. --_----------=_1071836924138022 Content-Disposition: inline Content-Length: 650 Content-Transfer-Encoding: binary Content-Type: text/plain Jerzy Karczmarczuk wrote > RWS says that he doesn't like this design. > I would say more, I find it not really acceptable. Data structures which explode under your nose are against the Golden Functional Way of Life. This design is used all the time. See for instance the way opening and closing files works. Not nice but it makes coding (with pattern matching) a little easier. Maybe one time Sparkle could help proving that a program never inspects a value that could explode. Then you have the best of both worlds. > 2. Does the Clean Respectable Team still think about the concurrency? That must be a no then. Regards Erik Zuurbier --_----------=_1071836924138022-- From ronny@cs.kun.nl Fri, 19 Dec 2003 14:05:11 +0100 Date: Fri, 19 Dec 2003 14:05:11 +0100 From: Ronny Wichers Schreur ronny@cs.kun.nl Subject: [clean-list] Some examples about the Directory library Erik Zuurbier writes (to the Clean Discussion list): >This design is used all the time. See for instance the way >opening and closing files works. > I don't like it there either. >Not nice but it makes coding (with pattern matching) a little >easier. > So we need pattern guards # (r, f) = freadc f | Nothing <- r = ... | Just c <- r = ... c ... and an optimisation to make sure that Nothing and Just are not allocated if efficiency is important. >Maybe one time Sparkle could help proving that a program >never inspects a value that could explode. Then you have the >best of both worlds. > This is something that can be expressed in Clean's current type system, so I'd prefer that. Cheers, Ronny Wichers Schreur From fzuurbie@inter.nl.net Tue, 23 Dec 2003 12:11:13 UT Date: Tue, 23 Dec 2003 12:11:13 UT From: fzuurbie@inter.nl.net fzuurbie@inter.nl.net Subject: [clean-list] Joe Armstrong's thesis This is a multi-part message in MIME format. --_----------=_1072181473238090 Content-Disposition: inline Content-Length: 5157 Content-Transfer-Encoding: binary Content-Type: text/plain Dear all, On 12 December Claus Reinke pointed me to Joe Armstrong's thesis about Erlang: Making reliable systems in the presence of software errors (http://www.sics.se/~joe/index.html). I promised not to talk about exception handling until I read it. So I read it. Erlang's starting points are quite alien to me. Armstrong says Erlang is strict, but he does not say why. John Hughes in his famous paper "Why Functional Programming Matters" points out the contribution of lazy evaluation to program correctness. On page 87 Armstrong writes: "The reason for this [EZ: concentrate concurrency handling in a few modules] is that concurrent code cannot be written in a side-effect free manner, and as such, is more difficult to understand and analyse than purely sequential side-effcect free code." This may be true for Erlang, but had he known about Marco Kesseler's implementation of Clean on Transputers, he would have known this does not hold in general, but only for applications that have inherent non-deterministic aspects. Erlang is dynamically typed and features side-effects. Armstrong does not reflect on these design decisions, in particular on their effect on program correctness. He does not give the impression he is even aware of static typing and other compile type program analysis methods to further correctness. These observations lead me to believe that everything has been done in the design and implementation of the Erlang language and compiler to make sure that programming errors will be made, if only to prove that systems will function nonetheless. His programming guide lines also reflect this. Page 126: "Rule: 1 - The program should be isomorphic to the specification. The program should faithfully follow the specification. If the specification says something silly then the program should do something silly. The program must faithfully reproduce any errors in the specification." Armstrong does not even consider the option to go back to the customer and question the specifications. I confess there are cases where I have not the faintest idea what a compiler error message means. Particularly Clean's uniqueness coercion messages can give me a hard time. In such cases I may dream of an executable that does run time checks and shows me what goes wrong. But for production quality software, Erlang's and Clean's road to reliability are very different. One point is interesting, although it does not sound completely new: the way to handle exceptions such as heap and stack overflows. Armstrong describes supervisors: processors that supervise other processors. As processors are isolated, a supervisor can generally continue operations when a supervised processor suffered a heap or stack overflow. Explicit message passing as the only way to parallellism, Erlang's view on exception handling and (other) side-effecting operations completely destroy referential transparency, thereby denying the programmer another road to program correctness. All in all, I think reading the thesis was a waste of time. Apart from one thing: Armstrong's work reassures me in thinking that exception handling may be implemented in a way that retains referential transparency / purity – on some level. In the implementations I know of, after an exception occurred, a programmer is completely free to specify what the program should do next. I think that liberty should be dropped. TCP/IP does that: a time-out exception (an acknowledgement message for a packet was not received in time) is followed by a resend ad infinitum. This is completely outside the programmer's control. [I am aware that programmers also have the means to break this cycle, but that is not what I am talking about here.] Anyway, I believe that in case of an exception, the program should not 'step aside' (do just anything) but 'freeze' (until the user loses his patience) or better still 'go forward' (try other ways to achieve the same effect). I hinted at other ways to achieve 'the same effect' in an earlier posting: In case of an integer overflow, redo the calculation with unlimited precision, if a connection times out, try a different connection, if a database machine does not respond, post an OS-message to the operator and resume activities when the problem is fixed, when retrying does not seem to solve a problem, the operating system could even halt operations, have the bug fixed and resume after that. I am well aware that in this latter case, the semantics of the program may change, so you can hardly say that the program will have 'the same effect'. This shows that this approach should start out as a sincere intention. In a later stage that could be backed up by static analysis. So initially, you could prove a program to be only conditionally correct: IF the semantics of an exception handler is in a way equivalent to the semantics of the non-exceptional case. This all should have the effect that when an application does not respond, the user will have confidence that the operating system is aware of this and that all feasible options are being tried to achieve the desired result. Regards Erik Zuurbier --_----------=_1072181473238090-- From brent.fulgham@xpsystems.com Tue, 23 Dec 2003 13:04:33 -0800 Date: Tue, 23 Dec 2003 13:04:33 -0800 From: Brent Fulgham brent.fulgham@xpsystems.com Subject: [clean-list] Joe Armstrong's thesis > Erlang's starting points are quite alien to me. Armstrong > says Erlang is strict, but he does not say why. John Hughes > in his famous paper "Why Functional Programming Matters" > points out the contribution of lazy evaluation to program correctness. Erlang is strict in the same sense Scheme is strict, plus a single-assignment behavior. > Erlang is dynamically typed and features side-effects. > Armstrong does not reflect on these design decisions, in > particular on their effect on program correctness. He does > not give the impression he is even aware of static typing and > other compile type program analysis methods to further correctness. I think he is probably aware of these concepts, at least in passing, since he has taken part in the "Lightweight Languages" workshops at MIT. These panel discussions often featured static typing critiques and other similar topics. > All in all, I think reading the thesis was a waste of time. > Apart from one thing: Armstrong's work reassures me in > thinking that exception handling may be implemented in a way > that retains referential transparency / purity - on some > level. When this discussion thread ended recently, I didn't feel that any meaningful conclusion had been reached. Lots of points of view, but no clear definition of how it should behave. > This all should have the effect that when an application does > not respond, the user will have confidence that the operating > system is aware of this and that all feasible options are > being tried to achieve the desired result. > Yes -- these ideas sound great, especially from a user-interface perspective. There are so many cases where we explain what the error is in great detail, but don't correct the problem automatically (even though we know how to do so.) -Brent From m.wittebrood@mailbox.kun.nl Tue, 23 Dec 2003 22:55:15 +0100 Date: Tue, 23 Dec 2003 22:55:15 +0100 From: Marco Kesseler m.wittebrood@mailbox.kun.nl Subject: [clean-list] Clean in the Real World >On 17-Dec-2003, Marco Kesseler wrote: >> In terms of the official semantics, this may be referential >> transparant. In terms of what the programmer sees and experiences, it >> is not. THAT is something that I do not like at all. > >Well, the point is that all operations which might deliver different >results each time are specially marked, e.g. by putting them in the >IO Monad. Programmers know that operations in the IO Monad might >deliver different results each time. > >This is the reality of programming in "pure" languages: they don't >actually prevent the use of all the impure constructs of imperative >languages, indeed they allow such constructs, complete with most of >the drawbacks for reasoning about programs that such constructs imply. >What these languages do is to just explicitly flag such constructs as >being impure, by putting them in the IO Monad (or equivalent), so that >programmers can safely apply equational reasoning to the parts of the >program which do not use them. This reality of Haskell may not be entirely the same in Clean. But I don't really want to end up in a discussion about the relative merits of Monads versus explicitly passing a unique world. What I do not like, is NOT that one CAN model inherently imperative stuff IN a functional language. It is rather that I question whether one SHOULD. Would it be THAT BAD if I/O gets programmed in an imperative language, which subsequently calls pure functional code for doing the processing? In a straightforward way, I mean. It would certainly separate the impure constructs from the pure ones. To be completely honest, I find it slightly disappointing if a solution encompasses Monads or similar. Disturbing too. It this the future of functional programming? Marco From t.zielonka@students.mimuw.edu.pl Wed, 24 Dec 2003 00:04:53 +0100 Date: Wed, 24 Dec 2003 00:04:53 +0100 From: Tomasz Zielonka t.zielonka@students.mimuw.edu.pl Subject: [clean-list] Clean in the Real World On Tue, Dec 23, 2003 at 10:55:15PM +0100, Marco Kesseler wrote: > > Would it be THAT BAD if I/O gets programmed in an imperative > language, which subsequently calls pure functional code for doing the > processing? In a straightforward way, I mean. It would certainly > separate the impure constructs from the pure ones. This quite a good description of what Haskell does. > To be completely honest, I find it slightly disappointing if a > solution encompasses Monads or similar. Disturbing too. It this the > future of functional programming? After some getting used to it, Monads are a pleasure to work with. If there is anything in Haskell that gets in my way, it ain't Monads. Best regards, Tom -- .signature: Too many levels of symbolic links From greenrd@greenrd.org Wed, 24 Dec 2003 01:43:29 +0000 Date: Wed, 24 Dec 2003 01:43:29 +0000 From: Robin Green greenrd@greenrd.org Subject: [clean-list] Clean in the Real World On Wed, Dec 24, 2003 at 12:04:53AM +0100, Tomasz Zielonka wrote: > > To be completely honest, I find it slightly disappointing if a > > solution encompasses Monads or similar. Disturbing too. It this the > > future of functional programming? > > After some getting used to it, Monads are a pleasure to work with. If > there is anything in Haskell that gets in my way, it ain't Monads. But do you think the average "Visual Basic for Dummies" type of programmer could get to grips with it? If so, please point me towards a simple "Monads for Dummies" document. I would like to read it. ;-) If not, I will continue to advocate for doing I/O type stuff in imperative languages. -- Robin From t.zielonka@students.mimuw.edu.pl Wed, 24 Dec 2003 09:08:48 +0100 Date: Wed, 24 Dec 2003 09:08:48 +0100 From: Tomasz Zielonka t.zielonka@students.mimuw.edu.pl Subject: [clean-list] Clean in the Real World On Wed, Dec 24, 2003 at 01:43:29AM +0000, Robin Green wrote: > On Wed, Dec 24, 2003 at 12:04:53AM +0100, Tomasz Zielonka wrote: > > > > After some getting used to it, Monads are a pleasure to work with. If > > there is anything in Haskell that gets in my way, it ain't Monads. > > But do you think the average "Visual Basic for Dummies" type of programmer > could get to grips with it? Why not? I don't feel qualified to judge who can or can't learn something. I think I have acquired quite a good (informal) understanding of monads. Besides IO monad I often use various other monads also in combination with monad transformers. I also define my own monad classes and types achieving increased modularity and even efficiency. Yet I have _zero_ knowledge about category theory and little formal preparation in functional programming (I was taught SML in a one semester course). My way to learn monads was by small experiments, thinking and use in small to medium sized programs. I paid with a couple day headache for freeing myself from the mainstream programming language mind-cage. Then about a month before I got quite comfortable with monads. So be prepared for hard work, but one that really pays off. > If so, please point me towards a simple "Monads for Dummies" document. > I would like to read it. ;-) I didn't use such a tutorial then, but please try first three links in section ,,Using Monads'' of http://www.haskell.org/bookshelf > If not, I will continue to advocate for doing I/O type stuff in > imperative languages. I hope you won't :) Best regards, Tom -- .signature: Too many levels of symbolic links From hoakley@btconnect.com Sun, 28 Dec 2003 13:17:49 +0000 Date: Sun, 28 Dec 2003 13:17:49 +0000 From: Howard Oakley hoakley@btconnect.com Subject: [clean-list] Request replacement Mac OS X CarbonInterface files Currently, the HTML and FTP downloads of Clean 2.1 for Mac OS X (ready-built) are delivering a Stuffit archive which is broken under Stuffit Deluxe 8.0.2. I have been able to manually extract almost everything, but three files have been damaged and will not extract. I would therefore be very grateful if someone could email them to me off list at hoakley btconnect com. The files are from Libraries/CarbonInterface/, and are: controls.icl desk.dcl desk.icl I have bodged (from 1.3's Carbon interface) the first and assume the latter two are essentially empty in this release, but would greatly appreciate copies of the files to be sure! (FYI, new to list but returned to Clean after long absence awaiting OS X release; running 10.3.2 on G5 DP 2 gig.) Thanks & season's greetings, Howard. Dr Howard Oakley Isle of Wight, UK From diederik@cs.kun.nl Sun, 28 Dec 2003 16:26:04 +0100 Date: Sun, 28 Dec 2003 16:26:04 +0100 From: Diederik van Arkel diederik@cs.kun.nl Subject: [clean-list] Request replacement Mac OS X CarbonInterface files On Dec 28, 2003, at 2:17 PM, Howard Oakley wrote: > Currently, the HTML and FTP downloads of Clean 2.1 for Mac OS X > (ready-built) are delivering a Stuffit archive which is broken under > Stuffit > Deluxe 8.0.2. I have been able to manually extract almost everything, > but > three files have been damaged and will not extract. I would therefore > be > very grateful if someone could email them to me off list at hoakley > > btconnect com. > > The files are from Libraries/CarbonInterface/, and are: > controls.icl > desk.dcl > desk.icl > I have bodged (from 1.3's Carbon interface) the first and assume the > latter > two are essentially empty in this release, but would greatly appreciate > copies of the files to be sure! > > (FYI, new to list but returned to Clean after long absence awaiting OS > X > release; running 10.3.2 on G5 DP 2 gig.) > Welcome back! I have mailed you your missing files off-list. Unpacking the archives works for me with the current Stuffit Expander on 10.3.2 so I suppose it is either a problem with the Deluxe version or with your downloads. Let us know if you find out anything more. Regards, Diederik van Arkel From hoakley@btconnect.com Sun, 28 Dec 2003 17:28:51 +0000 Date: Sun, 28 Dec 2003 17:28:51 +0000 From: Howard Oakley hoakley@btconnect.com Subject: [clean-list] Request replacement Mac OS X CarbonInterface files On 28/12/03 3:26 pm, Diederik van Arkel wrote: > Welcome back! I have mailed you your missing files off-list. Thank you very much indeed, Diederik. Whilst I guessed the correct implementation of SetControlVisibility, you have changed NewControl from 1.3, so I am pleased to be up to date now! > Unpacking > the archives > works for me with the current Stuffit Expander on 10.3.2 so I suppose > it is either > a problem with the Deluxe version or with your downloads. Let us know > if you find out anything more. I suspect this is a transient error, although it persisted across several downloads today (and I did clear my local cache to ensure I wasn't just getting the file from that). It failed halfway through decompression with Expander 8.0.2, but Deluxe app could open it and allowed manual recovery of everything else, so the error would appear to be somewhere around those files in the archive. I'll be delighted to spend some time with your very welcome OS X implementation over the next week or so, and report back. Were the tools compiled with the new Panther release of GCC, or would it be worth my while rebuilding them here to see if I can gain some performance on the G5? So far working through the examples looks really good, although there is a runtime error in Scrabble that I have to look at. Regards, Howard. Dr Howard Oakley Isle of Wight, UK From diederik@cs.kun.nl Mon, 29 Dec 2003 15:21:55 +0100 Date: Mon, 29 Dec 2003 15:21:55 +0100 From: Diederik van Arkel diederik@cs.kun.nl Subject: [clean-list] Stuffit8 and Clean 2.1 for MacOS X For those having problems unpacking the Clean 2.1 archive with Stuffit 8 on the Macintosh, the problem has been reported at AladdinSys. Workarounds are either unpack with a copy of StuffIt 7 or download the alternative archive I have temporarily put up at . Happy New Year, Diederik van Arkel