# Hugs
Hugs is an interpreter for the Haskell programming language.
It is a good solution for small systems, needing very little disk space and memory. It is much slower than GHC when evaluating code, but it starts almost instantaneously.
It has nicer error reporting than GHC. But it supports far fewer language extensions than GHC.
However, it is no longer maintained, and the Debian package is orphaned.
# 1 Behaviour
Hugs behaves differently from GHC in some ways.
# 1.1 fromInteger
In Hugs,
fromInteger :: Integer -> Int
throws arithmetic overflow exceptions on out of range.
In GHC it truncates silently.
# 1.2 round
In Hugs,
round (1/0) :: Integer
throws arithmetic overflow.
In GHC a large number is returned silently.
Similar behaviour in ceiling
, floor
, truncate
.
# 1.3 log
In Hugs,
log 0
throws an argument out of range exception.
In GHC it returns negative infinity.
In Hugs,
log (-10)
throws an argument out of range exception.
In GHC it returns NaN.
In Hugs,
log (0/0)
throws an argument out of range exception.
In GHC it returns NaN.
# 1.4 sqrt
Similar to log
, apart from sqrt 0
is ok.
# 2 Patches
Hugs has some bugs. Here are some I found, with fixes.
Patches against apt source hugs98
on Debian testing/Bookworm.
# 2.1 toInteger
Problem: toInteger (minBound :: Int)
returns nonsense on 64-bit systems.
May also affect 32bit systems, but I haven’t checked (I checked on Debian Linux).
Cause: -INT_MIN == INT_MIN
.
Symptoms: bitwise operations on Integer
throw arithmetic overflow exceptions.
Solution:
diff -wur old/hugs98-98.200609.21/src/bignums.c new/hugs98-98.200609.21/src/bignums.c
--- old/hugs98-98.200609.21/src/bignums.c 2004-10-29 13:43:09.000000000 +0100
+++ new/hugs98-98.200609.21/src/bignums.c 2023-02-01 11:15:18.575315477 +0000
@@ -117,7 +117,7 @@
unsigned long no;
Cell nx;
if (n<0) {
- no = (unsigned long)(-n);
+ no = (unsigned long)(-(signed long)(n));
bn = pair(NEGNUM,NIL);
}
else {
# 2.2 isNaN and friends
Problem: isNaN
and friends always return False
.
Cause: they’re implemented that way.
Symptoms: code that checks floating point values are ok to handle errors does nothing, then later code that assumes finite values throws arithmetic overflow exceptions.
Solution:
diff -wur old/hugs98-98.200609.21/libraries/hugsbase/Hugs/Prelude.hs new/hugs98-98.200609.21/libraries/hugsbase/Hugs/Prelude.hs
--- old/hugs98-98.200609.21/libraries/hugsbase/Hugs/Prelude.hs 2006-05-03 10:10:40.000000000 +0100
+++ new/hugs98-98.200609.21/libraries/hugsbase/Hugs/Prelude.hs 2023-02-02 15:47:18.561731245 +0000
@@ -275,6 +275,9 @@
scaleFloat :: Int -> a -> a
isNaN, isInfinite, isDenormalized, isNegativeZero, isIEEE
:: a -> Bool
+ isNaN x = not (x == x)
+ isInfinite x = (1 / x) == 0
+ isNegativeZero x = x == 0 && 1 / x < 0
atan2 :: a -> a -> a
-- Minimal complete definition: All, except exponent, signficand,
@@ -972,10 +975,7 @@
floatRange _ = (primFloatMinExp, primFloatMaxExp)
encodeFloat = primFloatEncode
decodeFloat = primFloatDecode
- isNaN _ = False
- isInfinite _ = False
isDenormalized _ = False
- isNegativeZero _ = False
isIEEE _ = False
primitive primDoubleRadix :: Integer
@@ -991,10 +991,7 @@
floatRange _ = (primDoubleMinExp, primDoubleMaxExp)
encodeFloat = primDoubleEncode
decodeFloat = primDoubleDecode
- isNaN _ = False
- isInfinite _ = False
isDenormalized _ = False
- isNegativeZero _ = False
isIEEE _ = False
instance Enum Float where