Re: replacing the Prelude (again)

Hi again, Malcolm writes:
We came across the same problem in the Hat tracer (which is also a source-to-source transformation, and can also be used for debugging).
The problem is that the transformation introduces new classes, so Prelude.Ord -> HatPrelude.Ord Prelude.Eq -> HatPrelude.Eq Prelude.Num -> HatPrelude.Num
The defaulting mechanism *only* applies to types constrained by the original builtin Prelude.Num, not to the transformed class HatPrelude.Num.
I did wonder how Hat tackled this. Out of curiosity what is the solution that Hat uses? And what is the situation in nhc98?
I think you are saying that if we import HatPrelude as Prelude together with -fno-implicit-prelude in GHC, then defaulting should work over the HatPrelude classes rather than the Prelude ones?
That's what I had hoped for.
Unfortunately, in Hat at least, we continue to use the original Prelude in *addition* to the replacement HatPrelude.
This adds an extra element of difficulty to the problem. I am trying my hardest to avoid needing the to import the original Prelude in a transformed module - this requires quite a bit of desugaring in the transformation. Still, I would like to be able to use do notation and have it refer to Prelude.Monad, not MyPrelude.Monad. I can live without it of course. For what reasons do you require the original prelude? Cheers, Bernie.

The defaulting mechanism *only* applies to types constrained by the original builtin Prelude.Num, not to the transformed class HatPrelude.Num.
I did wonder how Hat tackled this. Out of curiosity what is the solution that Hat uses?
Hat doesn't have a solution. When the lack of correct defaulting causes Hat to generate type-incorrect code, the underlying compiler will complain vociferously. Our advice to users is to write `default ()' at the top of the module, then resolve the type errors they get from the normal compilation so that defaulting is completely eliminated. The code will then go through Hat smoothly. It isn't very satisfactory, but in practice, defaulting doesn't really occur very often, so it isn't too much of a hardship. Ideally, the solution is a language design issue. Defaults are currently very implicit, second-class things. It would be much better if we could have a more generalised defaulting mechanism, applicable to any class. For instance default Num (Integer, Double) default Monad (IO) default MyClass (MyType) or something - at the least an association of a set of types with a named class. Maybe more is required.
This adds an extra element of difficulty to the problem. I am trying my hardest to avoid needing the to import the original Prelude in a transformed module - this requires quite a bit of desugaring in the transformation.
For what reasons do you require the original prelude?
Exactly the same reasons. We want to do as little desugaring as necessary in the transformation, so inevitably we need at least a small part of the Prelude in scope. Regards, Malcolm

Malcolm Wallace wrote:
For what reasons do you require the original prelude?
Exactly the same reasons. We want to do as little desugaring as necessary in the transformation, so inevitably we need at least a small part of the Prelude in scope.
This is a bit misleading. We do desugar as far as possible anything that refers to prelude functions, e.g. list comprehensions and do notation (these constructs could still be traced specially, although currently this is not the case). However, the transformed program does contain numeric literals and according to the Haskell 98 definition a compiler will add an implicit fromInteger etc to every such literal. According to Haskell 98 this fromInteger always refers to the Prelude. We want to produce Haskell 98 code and hence do not want to rely on any non-standard -no-implicit-prelude option, but we may use it circumvent the current problem of lack of defaulting. (Our transformation does add its own TPrelude.fromInteger to every literal, but that is a separate issue). At the moment I cannot think of any other original Prelude function in a transformed program. Naturally the transformed Prelude and also our tracing combinators use the original Prelude heavily. Btw Bernie, I'm surprised you say that transforming the Prelude was no problem for you. It did take me quite a lot of time. The problem is that altough most of it is just Haskell, some parts are primitive. So the Prelude has to be split into a transformable part and a core part, the tracing version of which needs to be written by hand. Also the Prelude and some standard library modules are mutually recursive, which no Haskell compiler handles easily. Hence I defined one large module, from which both Prelude and some standard libraries import, but only export parts of it. It is also tricky to avoid recursive dependencies between core and transformable parts. Ciao, Olaf -- OLAF CHITIL, Dept. of Computer Science, The University of York, York YO10 5DD, UK. URL: http://www.cs.york.ac.uk/~olaf/ Tel: +44 1904 434756; Fax: +44 1904 432767
participants (3)
-
Bernard James POPE
-
Malcolm Wallace
-
Olaf Chitil