There are five built-in type classes with the following instances:
Num: Int, Float
Eq: Bool, Char, Either a b, Float, Int, Maybe a, [a] and tuples
Ord: Bool, Char, Float, Int, [a] and tuples
Show: Bool, Char, Either a b, Float, Int, Maybe a, Ordering, [a] and tuples
Enum: Bool, Char, Float, Int and ()
Instances for Show and Eq (and not for other classes)
can be derived for data types. These instances are needed to
use overloaded functions, such as show and (==)
If your main function is not of type IO, then the value is printed with the show functions. The show functions
can print anything, e.g. functions are printed as <<function>>. Therefore, there is
a difference between main = expression and main = show expression. In the
latter case, the expression must be in the Show class.
The module system is simple, but powerful enough for the purpose of Helium:
Everything is always exported: data types, functions, synonyms, instances.
Everything that is imported is exported as well.
It is not allowed to import something via two (different) import declarations.
This means that if you have a module A and both B and C import A, and then a fourth
module D imports both B and C, then you will get clashes for all the names in A.
from module A. However, it is no problem if module A is the Prelude
You can hide functions in an import declaration with hiding, except for the
show functions that are generated for a data type. Other entities, such as types and constructors,
cannot be hidden.
The Prelude is always imported. You can hide functions from
the Prelude by explicitly writing an import declaration: import Prelude hiding (map, filter)
The following character sequences are supported in characters and strings:
\\, \n, \a, \b, \f, \r, \t, \v, \", \'.
Other escape sequences like the ones with numbers are not supported.
Numeric literals are not overloaded (even when using the --overloading flag). Thus, 3 is of type Int and
3.0 is of type Float.
In Helium, type variables are always of kind star (*).
A more restrictive syntax for operator sections. For instance,
(+2*3) is not allowed, this should be (+(2*3)).
A slightly more restrictive syntax for left-hand sides of function definitions.
For example, in Helium the parentheses in the following definitions
are necessary whereas in Haskell they are not:
(x:xs) ++ ys = ...
(x:xs) = ...
Helium rejects a definition if operator precedence is necessary to understand the
left-hand side. See the end of section 4.4 (A note
about syntax) of the Haskell Report to see why we have done this.
Fixity declarations are only allowed at top-level
Integer is simply a type synonym for Int. This makes programs with the explicit type
Integer compile but, of course, this does not make Integers arbitrary precision.
Tuples with more than 10 elements are not supported.
Not in Haskell 98
A show function is generated for each data type and type synonym. For instance, the function showMaybe is
automatically created for the data type Maybe. If the data type has parameters, then the
show function gets extra arguments, e.g. showMaybe showInt (Just 3).