Hacle's Limitations

Hacle is not quite complete in the sense that a small number of translation issues have not been dealt with. As a result Hacle can only translate a subset of Haskell'98 programs.

The limitations from Haskell'98 are

Defaulting Overloaded Numbers

In Haskell numeric literals are overloaded, i.e. the type of the literal 1 could be Int, Integer, Float, or Double. As a result the type of the following function

  power x 0 = 1
  power x n = x * power x (n-1)
is
  power :: (Num a, Num b) => a -> b -> a

Therefore one would expect a Haskell compiler to complain about internal overloading in the following program, since it can't determine which version of the polymorphic function power is being referred to

  main = print (2 `power` 3)

But it won't complain. This is because every Haskell module assumes the implicit declaration

  default (Integer, Double)

Which informs a compiler the internal overloading of numbers should be resolved by first trying to assign them the type Integer, and if that fails then Double.

Clean 2.1 has no way to default like this. The reason for not solving this limitation is that the effort required to do so for the general case is sufficiently more than that of hand-removing it for a specific case.

To hand-remove the defaulting simply place the following declaration after the import declarations of the Haskell module which contains the internal overloading

  default ()

Then recompile the Haskell module with a compiler of your choice and act upon the resulting error messages by adding clarifying type-signatures to the code.

Standard Library Limitations

Of the standard Haskell'98 libraries, only the following modules are supported:

  • Prelude
  • Char
  • List
  • Maybe
  • Monad
  • Numeric
  • Ratio
  • Ix

The standard but inefficient Array module could probably be included in this list. A better option might be to write a compatible module by using Clean's array primatives.

Module Names

Module names may not conflict with any standard library module names.

Arbitrary Precision Integers

Arbitrary precision integers and arithmetic are not provided in Clean and so we do not provide support for the built-in type Integer. This results in a few Prelude limitations.

Prelude Limitations

The following limitations are consequences of the limitation Arbitrary Precision Integers
  • The fromInteger method of the Num class has the following type
      fromInteger :: (Num a) => Int -> a
    
  • Rationals cannot be supported. Consequently, we remove the method toRational from the Real class and fromRational from the Fractional class. Furthermore the following functions are aren't provided:

      realToFrac, fromRat, showEFloat,
      showEFloat, showGFloat, approxRational
    
  • A Double is not instantiated under RealFloat due to the lack of the necessary primatives for Clean's Reals.

Single Precision Floats

Clean only provides support for double-precision floating point numbers and so we do not provide support for the built-in type Float. However, most, if not all of the functionality of a Float can be achieved by interpreting it as a Double.

As a result you should account for the fact that Floats and Doubles are both translated to Clean's Reals (and so you can't instantiate them separately under the same type class since they will be treated as the same type by Hacle).

Type Synonyms in Curried Types

Though in the vast majority of cases Hacle successfully translates Haskell's curried type-signatures to Clean's non-curried style, there is a case when it doesn't do so and will simply ignore the type-signature. This can happen when the return type of a type-signature is a type synonym representing a function.

For example, suppose we have the following type synonym definition:

  type ReadS a = String -> [(a,String)]
and the following type-signature and function definition:
  lex :: ReadS String
  lex s = ...

To Hacle, the function lex takes no arguments (according to the type definition) and so it is confused when it sees the definition of lex taking the argument s as a parameter. As a result Hacle simply ignores lex's type-signature. This will only cause a problem when the function in question needs disambiguating. The chances of both of these situations arising at the same time is not particularly likely.

To translate the type-signature correctly Hacle would have to be able expand the type synonym.

Newtype Patterns

Unfortunatly I had a problem implementing my newtype pattern matching translation. As a result newtype patterns don't get translated as they should. This may get fixed in the future.