Re: [Haskell] Type Lambdas in Gofer
Jim Apple wrote: data Rec f = In (f (Rec f)) type P f a = f (Rec f, a) mapP :: Functor f = (a - b) - P f a - P f b mapP g = fmap (\(x,a) - (x, g a)) instance Functor f = Functor (P f) where fmap = mapP Why did Gofer have this power while Haskell does not? Haskell does have the same power as Gofer, it simply does not allow you to define instances for type synonyms (just in order to prevent overlapping instances, I guess). If you use a newtype instead of a type synonym everything works fine: data Rec f = In (f (Rec f)) newtype P f a = P (f (Rec f, a)) unP (P x) = x mapP :: Functor f = (a - b) - P f a - P f b mapP g = P . fmap (\((x,a)) - (x, g a)) . unP instance Functor f = Functor (P f) where fmap = mapP Wolfgang ___ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell
Re: [Haskell] Haskell 98 syntax question
Sascha Böhme wrote: Hello, referring to the Haskell 98 report as available in the Internet, I have a short question. Section 4.1.3 (Syntax of Class Assertions and Contexts) contains the rule: class - qtycls tyvar | qtycls ( tyvar atype1 ... atypen ) (n=1) Is there a (simple) practical example of a Haskell type expression using the second line of the above rule? If you read a little bit further, you'll find the type (Eq (f a), Functor f) = (a - b) - f a - f b - Bool in Sect 4.1.4. Another example can be found in Sect. 4.5.3: f :: (Monad m, Eq (m a)) = a - m a - Bool f x y = return x == y Regards Wolfgang ___ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell
Re: [Haskell] Mixing monadic and non-monadic functions
Frederik Eaton wrote: I want the type system to be able to do automatic lifting of monads, i.e., since [] is a monad, I should be able to write the following: and have it interpreted as do {a-[1,2]; b-[3,4]; return (a+b)}. Are you sure that this is the interpretation you have in mind? The expression do {a-[1,2]; b-[3,4]; return (a+b)} does *not* compute the element-wise sum of the two lists, but returns the list [4,5,5,6]. To me, this would be a very counter intuitive result for an expression [1,2]+[3,4]. Wolfgang ___ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell
Re: [Haskell] readList oddity
Am 21.10.2004 um 09:55 schrieb Johannes Waldmann: turns out that check1 and check2 work, but check0 will not (I thought it would). The implementation (in the Prelude) seems to think that ] (in check0) could possibly be the beginning of a list element. This is just a problem of non-deterministic parsing. The prelude's read function always explores all possible parses (in order to flag ambiguous ones). Thus, at the beginning of the list it will always try to match the input against ] and an element causing check0 to fail. For later elements there is no problem because the choice is between ] and ,. Because of that, calling error in one of your read functions seems a bad idea. In fact, returning an empty list is the right way to return an error in the prelude's parsing framework. If you want something different (e.g., because you want better error messages) you should not be using the prelude's read function. IMHO, the prelude's Read class for that reason is quite useless -- except for converting strings into numbers. Wolfgang ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: [Haskell] return?
John Meacham wrote: you can make things somewhat better with this construct foo = do baz if cond then return bar else do bua bam Except that this is invalid according to the Haskell report. In note 1 in section 9.3 (Layout), the report explicitly states that A nested context must be further indented than the enclosing context. While hugs and ghc incorrectly accept your code, hbc and nhc98 get it right, i.e., they raise a parse error on it. Wolfgang ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: The madness of implicit parameters: cured?
Ben Rudiak-Gould wrote: [...] The final straw was: Prelude let ?x = 1 in let g = ?x in let ?x = 2 in g 1 Prelude let ?x = 1 in let g () = ?x in let ?x = 2 in g () 2 This is insanity. I can't possibly use a language feature which behaves in such a non-orthogonal way. Well, this is not insanity (only a little bit). In the first example, you define a *value* g, i.e., g is bound to the value of ?x in its current environment (though this value is not yet evaluated due to lazy evaluation), whereas in the second example you define a function. The real insanity in this point is that Haskell -- in contrast to Clean -- offers no way to distinguish function bindings and value bindings and therefore you cannot define nullary functions (except by some judicious use type signatures), which is the heart of the monomorphism restriction mentioned by somebody else on this list (and discussed regularly on this list :-). Now the interesting part: I think I've managed to fix these problems. I'm afraid that my solution will turn out to be just as unimplementable as my original file I/O proposal, and that's very likely in this case since I'm far from grokking Haskell's type system. So I'm going to present my idea and let the gurus on this list tell me where I went wrong. Here we go. [...] Now introduce the idea of explicit named parameters to Haskell. This requires three extensions: a new kind of abstraction, a new kind of application, and a way of representing the resulting types. This looks quite similar to the labeled parameters in Objective Caml. However, Objective Caml's solution seems to be more general. For instance, you can pass labeled parameters in arbitrary order and you can have default value for optional arguments. [...] Why are the semantics so much clearer? I think the fundamental problem with the existing semantics is the presence of an implicit parameter environment, from which values are scooped and plugged into functions at hard-to-predict times. If you keep the distinction between values and functions in mind, I do not think that it is hard to predict when an implicit parameter is substituted (if you are willing to accept the principal problem that it is hard to predict which value is substituted with every kind of dynamic scoping :-). By substituting a notation which clearly means I want this implicit parameter of this function bound to this value right now, and if you can't do it I want a static type error, we avoid this ambiguity. IMHO, this problem were solved much easier by introducing a new syntax to distinguish value and (nullary) function bindings, as was already repeatedly asked for on this list in the context of the monomorphism restriction. Personally, I'd suggest to use let x - e in ... to introduce a value binding (as it is quite similar to the bindings introduced in a do-statement) and use let x = e to introduce a nullary function. (I prefer - over := which John Hughes and others suggested some time ago because we don't loose an operator name). Thus, you example let ?x = 1 in let g = ?x in let ?x = 2 in g will behave as you did expect, viz. evaluate to 2, whereas let ?x = 1 in let g - ?x in let ?x = 2 in g will return 1. Regards Wolfgang ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: In search of: [a-b] - a - [b]
Christian Sievers wrote: This is a case where I'd prefer a list comprehension: flist fs a = [ f a | f - fs ] (and this could be a monad comprehension, if Haskell still had them...) And it still has them, you just have to get accustomed to the slightly different syntax :-) flist fs a = do f - fs; return (f a) Wolfgang ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: Scope of imported names
Karl-Filip Faxen wrote Section 5.5.2 relates to name clashes and has an interesting example towards the end: module F where sin :: Float - Float sin x = (x::Float) f x = Prelude.sin (F.sin x) where the type signature refers to the local sin rather than the imported although none of them is visible unqualified. These rules are quite tricky to understand, I think. They are also different in spirit from the rules The Haskell report seems to be inconsistent here (once again). In the beginning of section 5.3 it says Imported names serve as top level declarations: they scope over the entire body of the module but may be shadowed by local NON-TOP-LEVEL bindings. Thus, the definition of sin in module F is invalid because another top-level declaration of sin already exists due to the (implicit) import of the Prelude. In order to redefine sin locally the imported definition should be hidden and imported only qualified: module F where import Prelude hiding(sin) import qualified Prelude(sin) ... for instance declarations in section 4.3.2 where the binding occurrences for the names of the methods must be qualified if the unqualified method name is not in scope. In the sin example it is allowed to resolve the name clash using the extra knowledge that it is illegal to provide type signatures for imported names, wheras in the case for instance declarations we may not use the corresponding extra knowledge that only methods in the instance'd class may be bound by the bindings. What I'm driving at is this: I propose that top level bindings shadow imported names and that qualified names can not be used to refer to declarations in the same module. The second part is going to conflict with the revised report which relies on the qualified names of entities in order to specify which entites exported from module M (module M) where { ... } /kff who feels very relieved at having come out publicly in favour of shadowing imported names ;-) Wolfgang who prefers to forbid shadowing of imported names :-) -- Wolfgang Lux Phone: +49-251-83-38263 Institut fuer Wirtschaftinformatik FAX: +49-251-83-38259 Universitaet Muenster Email: [EMAIL PROTECTED] ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: Scope of imported names
Hello! Well, it's not that simple currently. Name clashes are only illegal if they lead to unresolvable references. Thus if we have Intricate, indeed. I didn't expect to be able to define a function which I cannot reference with its unqualified name. What I'm driving at is this: I propose that top level bindings shadow imported names and that qualified names can not be used to refer to declarations in the same module. The second part is going to conflict with the revised report which relies on the qualified names of entities in order to specify which entities export ed from module M (module M) where { ... } That's right (this refers to section 5.2, fifth numbered item). What is the rationale behind requiring the qualified name to be visible also? If I remember right (I didn't track this down in the mail archives), the reason was to clarify the meaning of an as clause on an import. I.e., the export list of module M(module N) import N as P should be empty, while module M(module P) import N as P exports all of the entities exported from module N. who prefers to forbid shadowing of imported names :-) Even by nested bindings? No. Otherwise you would probably ask me why I don't want to forbid shadowing of global names by local ones. However, I still don't like the proposal because it allows to shadow imported definitions without noticing. IMHO this is less a problem for local definitions inside a function (which is rarely more than few lines long and thus more easily comprehensible) than for a whole module. Wolfgang -- Wolfgang Lux Phone: +49-251-83-38263 Institut fuer Wirtschaftinformatik FAX: +49-251-83-38259 Universitaet Muenster Email: [EMAIL PROTECTED] ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: More feedback on Haskell 98 modules from the Programatica Team
Simon Peyton-Jones wrote | 2) The semantics of module M style entries in export lists seems to |Program 2: module A(module B, ...) where |~~ import qualified B | ... code that doesn't import B ... | |A similar example: now B appears as an import, but there are no |unqualified imports of B, so either module B adds nothing to the |export list (except instances?), or else this program is an error. | |Item 5 on p65 (describing entities exported from modules) says that |module m exports entities brought into scope from m by one or more |*unqualified* imports. But this example suggests more; that it will |export instances brought into scope from *qualified* imports too. |Perhaps the intention is that module m exports all instances, |and all entities that are imported from m with an unqualified name? I don't think it should matter whether B is imported qualified or not; I propose to remove the *unqualified* adjective in the above quote. I don't think that this is a good idea. In particular because it may break existing programs. Consider two modules with one common name, e.g. module A where f x = 1 ... a lot of other definitions ... module B where f x = 2 ... a lot more definitions but none conflicting with A's top-level entities ... The following module is legal under the current semantics of the report (and will export everything from A and B except for A.f and in particular will generate no names clashes in the body of the module module C (module A,module B,module C) where import A hiding(f) import qualified A(f) import B ... code using A.f and f (i.e. B.f) ... With your proposed change there will be a name clash for the export of f from module C. Wolfgang -- Wolfgang Lux Phone: +49-251-83-38263 Institut fuer Wirtschaftinformatik FAX: +49-251-83-38259 Universitaet Muenster Email: [EMAIL PROTECTED] ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: Simple compiler question
Mark Carroll wrote Do any of the decent Haskell compilers allow you to just type function definitions at an interpreter prompt and use them in subsequent interactions, as you'd expect from a Lisp environment? I don't know whether you consider hbi (the interactive version of hbc) a decent compiler, but it supports entering definitions as well: let { f x = x + x }; f :: (Prelude.Num a) = a - a f 3; 6 Wolfgang -- Wolfgang Lux Phone: +49-251-83-38263 Institut fuer Wirtschaftinformatik FAX: +49-251-83-38259 Universitaet Muenster Email: [EMAIL PROTECTED] ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: lexical description problem in language report?
Thomas Hallgren wrote There seems to be a similar problem with qualified identifiers. The production for lexeme includes varid, conid, etc, rather than qvarid, qconid, etc. (Perhaps someone forgot to update it when qualified names were introduced, in Haskell 1.3...) Sorry we must have a different version of the report, but in my copy and also in the version on Simon PJ's web-pages section 2.4 (in the last paragraph) and appendix B include productions for the qualified identifiers. Wolfgang -- Wolfgang Lux Phone: +49-251-83-38263 Institut fuer Wirtschaftinformatik FAX: +49-251-83-38259 Universitaet Muenster Email: [EMAIL PROTECTED] ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Minor inconsistency in the report wrt to qualified names
In section 5.5.1 the report states that a top-level declaration brings into scope qualified and unqualified names. Thus, the following declaration is legal: module Foo where ones = 1 : Foo.ones However, in section 2.4 the report says External names may optionally be qualified in certain circumstances by prepending them with a module identifier. And also in section 3.2 the report says Qualified names may only be used to reference and imported variable or constructor, from which the above program would not be legal (because Foo.ones is not an imported constructor or variable). In order to make the report consistent, I would suggest to change the section 3.2 to say: Qualified names may be used to reference variables or constructors which are imported from other modules or defined at the top level. In section 2.4, the word External should be dropped from the sentence. Wolfgang -- Wolfgang Lux Phone: +49-251-83-38263 Institut fuer Wirtschaftinformatik FAX: +49-251-83-38259 Universitaet Muenster Email: [EMAIL PROTECTED] ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: Dealing with implementation differences
Hello, How does one deal cleanly with implementation differences, e.g. things like isAscii being defined in Hugs but not in GHC? I'd hate to resort to Makefile trickery and preprocessing. You can try to use some special compatibility module where you collect all the workarounds for the implmentation differences. But in this particular you should better read the (library) report and simply import the Char module (from where isAscii should be exported -- Hugs still exports it from the Prelude though it shouldn't). Wolfgang -- Wolfgang Lux Phone: +49-251-83-38263 Institut fuer Wirtschaftinformatik FAX: +49-251-83-38259 Universitaet Muenster Email: [EMAIL PROTECTED] ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: infelicity in module imports
Brian Boutel wrote Option 2 is closer to what the syntax of imports, read as English, suggests is intended, but, if it wasn't for that, I'd be promoting option 1. The primary purpose of being able to restrict imports is to avoid name clashes, and with qualified import there is no risk of a clash, so no need for restrictions. This is not true since Haskell allows for the renaming of modules on imports. If you look at the example in section 5.3.2 of the report, there is the example module M where import qualified Foo as A import qualified Bar as A x = A.f Obviously there is a name clash if both, Foo and Bar export symbol f. Even with option 2, there is scope for confusion. Import without qualified, imports both qualified and unqualified names, but adding the word qualified doesn't make any difference to the position of qualified names, but instead silently fails to import unqualified names. I don't understand what confusion you see here. What do you mean by the position of names? There is still a strange asymmetry, too. Whereas adding qualified to import Modname ( a, b, c) doesn't change which entities are imported, just the ability to refer to them by unqualified names, adding qualified to import Modname hiding ( a, b, c) has the effect of importing everything that was previously hidden. I don't see that this applies to option 2. Maybe the formulation is still not clear enough, but in my reading (and I think this is the intended one) it says that the list of imported entities is the same regardless of whether you use qualified on the import or not. The qualified keyword only prevents the use of unqualified references to these entities. So if in your example the module Modname exports entities a, b, c, d, and e, then after import Modname hiding (a,b,c) only d and e are imported and then same is true for import qualified Modname hiding (a,b,c) Simon Peyton-Jones wrote: [...] There are two consistent positions 1. Every import of module A (no matter how constrained) imports all of A's exports with qualified names. Import of qualified names is unaffected by both hiding clauses and the explicit entity list 2. The explicit entity list, or hiding clause, for an import determines which entities are imported. The qualified names of all these entities are brought into scope; in addition, for an unqualified import the unqualified names are brought into scope too. Regards Wolfgang -- Wolfgang Lux Phone: +49-251-83-38263 Institut fuer Wirtschaftinformatik FAX: +49-251-83-38259 Universitaet Muenster Email: [EMAIL PROTECTED] ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: infelicity in module imports
Koen Claessen wrote What I would like to see in the report are *examples*. Namely what happens in each of the following cases: Ok, let me try: import A visible: x, y, p, q, v, w, A.x, A.y, A.p, A.q, A.v, A.w import A() nothing imported import A(x,y) visible: x, y, A.x, A.y import qualified A visible: A.x, A.y, A.p, A.q, A.v, A.w import qualified A() nothing imported import qualified A(x,y) visible: A.x, A.y import A hiding () like import A import A() hiding () import A(x,y) hiding () these two are not legal, you have either and list of included entities or a list of hidden entities both not both. import A hiding (p,q) according to report this would import x, y, v, w, A.x, A.y, A.p, A.q, A.v, A.w with the revision of the report A.p and A.q no longer are visible import A() hiding (p,q) import A(x,y) hiding (p,q) both are not legal import qualified A hiding () like import A import qualified A() hiding () import qualified A(x,y) hiding () both not legal import qualified A hiding (p,q) either A.x, A.y, A.p, A.q, A.v, A.w (according to the report) or A.x, A.y, A.v, A.w (when the report is changed as Simon proposed) import qualified A() hiding (p,q) import qualified A(x,y) hiding (p,q) both not legal Regards Wolfgang -- Wolfgang Lux Phone: +49-251-83-38263 Institut fuer Wirtschaftinformatik FAX: +49-251-83-38259 Universitaet Muenster Email: [EMAIL PROTECTED] ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Another question wrt hiding imports
After the recent discussion import hiding clauses in import declarations, I was wondering what the meaning of hiding clauses is in the case of algebraic data types (or classes). For instance if a have module A where data T = A | B which entities are imported when I include the declaration import A hiding(T) in a module? The report is not clear about this but I would expect that this imports data constructors A and B into the current module but not the type constructor T -- otherwise, what would be the meaning of import A hiding(T(B))? However, if this is true it is possible to export data constructors without their type via module B(module A) where import A hiding(T) which contradicts the statement in section 5.2 on p.64, that the form module m is equivalent to listing all entities imported from that module, because I cannot list a data constructor (without its type) in an export specification. Wolfgang -- Wolfgang Lux Phone: +49-251-83-38263 Institut fuer Wirtschaftinformatik FAX: +49-251-83-38259 Universitaet Muenster Email: [EMAIL PROTECTED] ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: Another question wrt hiding imports
Simon Peyton-Jones wrote | For instance if a have | | module A where | data T = A | B | | which entities are imported when I include the declaration | | import A hiding(T) | | in a module? The report is not clear about this but I would | expect that | this imports data constructors A and B into the current | module but not | the type constructor T Yes, that's right. Why is the report not clear? More precisely, how could I improve it? I find it a little bit counterintuitive to be able to hide a type constructor but not its data constructors (in particular) because one cannot import a data constructor by simply giving its name in an import specification. Maybe a single sentence which explicates the fact that hiding(T) only hides the type constructor T but not any of the data constructors of T (except if T is also a data constructor in this or any another data type) is sufficient to make this clear. (But maybe I was particularly dumb in this case). Wolfgang -- Wolfgang Lux Phone: +49-251-83-38263 Institut fuer Wirtschaftinformatik FAX: +49-251-83-38259 Universitaet Muenster Email: [EMAIL PROTECTED] ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: Fixity declarations
Koen Claessen wrote However, it is not possible to define the fixity of an operator which is an argument to a function. If I define: foldr4 :: (a - b - b) - b - (a,a,a,a) - b foldr4 (#) z (a,b,c,d) = a # b # c # d # z I will have to put in parentheses explicitly, because it is not possible to define the fixity of that entity (namely the argument (#) to foldr4). In this case, (#) gets the default fixity, namely infixl 9. Apart from the fact if we want to allow this or not, I think the report should be clear about that it is not possible to define the fixities of locally bound operator names in this way. Hmmm, unless I overlooked something your example is syntacally not valid by the grammar given in appendix B.4 of the Haskell 98 report. Operators in patterns can be used only with an infix syntax. Wolfgang -- Wolfgang Lux Phone: +49-251-83-38263 Institut fuer Wirtschaftinformatik FAX: +49-251-83-38259 Universitaet Muenster Email: [EMAIL PROTECTED] ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: infelicity in module imports
Malcolm Wallace wrote Currently, you are permitted to write import A hiding (f) import B as A (f) and this means that everything exported from module A is visible, with the exception that function `f' is overridden by a different definition from module B. Here, a reference to `A.f' is resolved unambiguously to `B.f'. In my understanding of the report, this is not true. Quoting from section 5.3 of the report The hiding clause only applies to unqualified names. In the previous example, the name M.C is brought into scope. Thus, in your example, the declaration import A hiding (f) will bring A.f into scope and thus A.f is ambiguous! Regards Wolfgang -- Wolfgang Lux Phone: +49-251-83-38263 Institut fuer Wirtschaftinformatik FAX: +49-251-83-38259 Universitaet Muenster Email: [EMAIL PROTECTED] ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: infelicity in module imports
Malcolm Wallace wrote However, if you are indeed correct, then we have an even stranger situation: import A (g) brings only A.g into scope, but import A hiding (f) brings both A.f and A.g into scope! So `hiding' is doing the opposite of hiding, and in fact _reveals_ names. Yes, I agree that this is quite strange (and the keyword hiding is quite misleading in this case). Probably, it is the best idea to remove the restriction that hiding clauses apply only to unqualified names from the report as you and Simon are suggesting. Regards Wolfgang -- Wolfgang Lux Phone: +49-251-83-38263 Institut fuer Wirtschaftinformatik FAX: +49-251-83-38259 Universitaet Muenster Email: [EMAIL PROTECTED] ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: Directory manipulation in Haskell 98
It seems that there is not a standard library for handling directories and directoreis entries in Haskell 98. I have just found the Posix library PosixFiles distributed with GHC 8.0.1 for that purpose. Hugs and NHC98 does not look like to have such a library. Is there a way to manipulate directory entries in a portable way in Haskell 98, or my only solution is to stick with GHC? Well. There is a standard library Directory (just have a look at the Haskell 98 Library Report under http://haskell.org/definition). The library is implemented by ghc, hbc and nhc. Unfortunately Hugs' implementation of this module is very incomplete. Regards Wolfgang -- Wolfgang Lux Phone: +49-251-83-38263 Institut fuer Wirtschaftinformatik FAX: +49-251-83-38259 Universitaet Muenster Email: [EMAIL PROTECTED]
Re: haskell operator precedence
Hi, Is the following legal Haskell? infixr 0 `foo` infixr 0 `bar` x `foo` y = "foo(" ++ x ++ "," ++ y ++ ")" x `bar` y = "bar(" ++ x ++ "," ++ y ++ ")" dubious a b c = a `foo` b `bar` c According to the grammar in the Haskell report, I don't think it is. However, ghc-0.24 (ancient, I know) and Hugs 1.3 both accept it without complaint. I haven't my copy of the Haskell report at hand, but I do not see why this should not be legal. You are declaring to right associative operators foo and bar with the same precedence. Your script wouldn't be legal if you had written infix 0 `foo` infix 0 `bar` and this will be rejected by Hugs as it should. Regards Wolfgang Wolfgang Lux WZH Heidelberg, IBM Germany Phone: +49-6221-59-4546Fax: +49-6221-59-3500 Internet: [EMAIL PROTECTED] Office: mazvm01(lux)