For a certain reason (weird Hugs installation on target computer) I want Haskell98 compliant code, which means no common language extensions. One annoyance in particular is the absence of multi-parameter typeclasses, for example in my case:
class Semiring d where
zero :: d
one :: d
plus :: d -> d -> d
times :: d -> d -> d
class Monoid e where
mzero :: e
mplus :: e -> e -> e
class (Semiring d, Monoid e) => Module d e where
mtimes :: d -> e -> e
I get a feeling that this issue in particular can be stepped around somehow, maybe by defining a few helper typeclasses and "packaging" the information about the types somehow, but I cannot figure it out.
Is my intuition justified at all? I am reading that multiparam typeclasses were widely used even at the time of Haskell98 standard's writing, were there ways of working around this limitation back then?

Oleg Kiselyov wrote a demonstration of this in 2007, Haskell with only one typeclass:
Briefly, he introduces a two-parameter class
Cwith a functional dependency and a single method:This relates a “label”
lwith its typet, for example:This isn’t strictly H98 because it uses a scoped type variable, but I believe those were implemented in Hugs fairly early on.
Now, as a multi-parameter class is effectively a set of tuples of types, we can rephrase it as a single-parameter class whose elements are tuples, at the loss of the functional dependency.
In modern Haskell, you may wish to use a proxy, but I’ve kept the use of undefined/bottom, both in the spirit of old-timey Haskell, and for the sake of similarity with the previous example.
Of course, the lack of a fundep now means that the compiler won’t be able to infer an unambiguous type in many cases, because it can’t determine that each label such as
Add Inthas only one corresponding signatureInt -> Int -> Int. So this may require a type annotation. On the other hand, it grants you some flexibility, in that you can technically give multiple types to the same term if you want to construct things like subtypes or overlapping instances. And if all you want to avoid is multi-parameter classes, then you can avoid a lot of the ambiguity by not restricting yourself to just one class.You can also encode functional dependencies manually using equality constraints, if they’re available:
Many more details and examples are in the article and accompanying code.