A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/bugs.html below:

Website Navigation


16. Known bugs and infelicities — Glasgow Haskell Compiler 9.12.2 User's Guide

16. Known bugs and infelicities¶ 16.1. Haskell standards vs. Glasgow Haskell: language non-compliance¶

This section lists Glasgow Haskell infelicities in its implementation of Haskell 98 and Haskell 2010. See also the “when things go wrong” section (What to do when something goes wrong) for information about crashes, space leaks, and other undesirable phenomena.

The limitations here are listed in Haskell Report order (roughly).

16.1.1. Divergence from Haskell 98 and Haskell 2010¶

GHC aims to be able to behave (mostly) like a Haskell 98 or Haskell 2010 compiler, if you tell it to try to behave like that with the Haskell98 and Haskell2010 flags. The known deviations from the standards are described below. Unless otherwise stated, the deviation applies in both Haskell 98 and Haskell 2010 mode.

16.1.1.1. Lexical syntax¶ 16.1.1.2. Context-free syntax¶
NondecreasingIndentation¶
Since:

7.2.1

Status:

Included in Haskell98

Allow nested contexts to be at the same indentation level as its enclosing context.

16.1.1.3. Expressions and patterns¶

By default, GHC makes some programs slightly more defined than they should be. For example, consider

f :: [a] -> b -> b
f [] = error "urk"
f (x:xs) = \v -> v

main = print (f [] `seq` True)

This should call error but actually prints True. Reason: GHC eta-expands f to

f :: [a] -> b -> b
f []     v = error "urk"
f (x:xs) v = v

For most programs this improves efficiency enough to be enabled & bad only in few rare cases. To suppress this optimisation use -fpedantic-bottoms.

16.1.1.4. Failable patterns¶

Since the MonadFail Proposal (MFP), do-notation blocks that contain a failable pattern need a MonadFail constraint.

For example

mayFail :: (MonadIO m) => m ()
mayFail = do
  (Just value) <- fetchData
  putStrLn value

Will warn you with

• Could not deduce (MonadFail m)
    arising from a do statement
    with the failable pattern ‘(Just x)’
  from the context: MonadIO m
    bound by the type signature for:
               mayFail :: forall (m :: * -> *). MonadIO m => m ()

And indeed, since the Monad class does not have the fail method anymore, we need to explicitly add (MonadFail m) to the constraints of the function.

16.1.1.5. Typechecking of recursive binding groups¶

The Haskell Report specifies that a group of bindings (at top level, or in a let or where) should be sorted into strongly-connected components, and then type-checked in dependency order (Haskell Report, Section 4.5.1). As each group is type-checked, any binders of the group that have an explicit type signature are put in the type environment with the specified polymorphic type, and all others are monomorphic until the group is generalised (Haskell Report, Section 4.5.2).

Following a suggestion of Mark Jones, in his paper Typing Haskell in Haskell, GHC implements a more general scheme. In GHC the dependency analysis ignores references to variables that have an explicit type signature. As a result of this refined dependency analysis, the dependency groups are smaller, and more bindings will typecheck. For example, consider:

f :: Eq a => a -> Bool
f x = (x == x) || g True || g "Yes"

g y = (y <= y) || f True

This is rejected by Haskell 98, but under Jones’s scheme the definition for g is typechecked first, separately from that for f, because the reference to f in g's right hand side is ignored by the dependency analysis. Then g's type is generalised, to get

Now, the definition for f is typechecked, with this type for g in the type environment.

The same refined dependency analysis also allows the type signatures of mutually-recursive functions to have different contexts, something that is illegal in Haskell 98 (Section 4.5.2, last sentence). GHC only insists that the type signatures of a refined group have identical type signatures; in practice this means that only variables bound by the same pattern binding must have the same context. For example, this is fine:

f :: Eq a => a -> Bool
f x = (x == x) || g True

g :: Ord a => a -> Bool
g y = (y <= y) || f True
16.1.1.6. Default Module headers with -main-is¶

The Haskell2010 Report specifies in <https://www.haskell.org/onlinereport/haskell2010/haskellch5.html#x11-990005.1> that

“An abbreviated form of module, consisting only of the module body,

is permitted. If this is used, the header is assumed to be module Main(main) where.”

GHC’s -main-is option can be used to change the name of the top-level entry point from main to any other variable. When compiling the main module and -main-is has been used to rename the default entry point, GHC will also use the alternate name in the default export list.

Consider the following program:

-- file: Main.hs
program :: IO ()
program = return ()

GHC will successfully compile this module with ghc -main-is Main.program Main.hs, because the default export list will include program rather than main, as the Haskell Report typically requires.

This change only applies to the main module. Other modules will still export main from a default export list, regardless of the -main-is flag. This allows use of -main-is with existing modules that export main via a default export list, even when -main-is points to a different entry point, as in this example (compiled with -main-is MainWrapper.program).

-- file MainWrapper.hs
module MainWrapper where
import Main

program :: IO ()
program = putStrLn "Redirecting..." >> main

-- file Main.hs
main :: IO ()
main = putStrLn "I am main."
16.1.1.7. Module system and interface files¶

GHC requires the use of hs-boot files to cut the recursive loops among mutually recursive modules as described in Mutually recursive modules and hs-boot files. This more of an infelicity than a bug: the Haskell Report says (Section 5.7)

“Depending on the Haskell implementation used, separate compilation of mutually recursive modules may require that imported modules contain additional information so that they may be referenced before they are compiled. Explicit type signatures for all exported values may be necessary to deal with mutual recursion. The precise details of separate compilation are not defined by this Report.”

16.1.1.8. Numbers, basic types, and built-in classes¶
Num superclasses

The Num class does not have Show or Eq superclasses.

You can make code that works with both Haskell98/Haskell2010 and GHC by:

Bits superclass

The Bits class does not have a Num superclass. It therefore does not have default methods for the bit, testBit and popCount methods.

You can make code that works with both Haskell 2010 and GHC by:

Read class methods

The Read class has two extra methods, readPrec and readListPrec, that are not found in the Haskell 2010 since they rely on the ReadPrec data type, which requires the RankNTypes extension. GHC also derives Read instances by implementing readPrec instead of readsPrec, and relies on a default implementation of readsPrec that is defined in terms of readPrec. GHC adds these two extra methods simply because ReadPrec is more efficient than ReadS (the type on which readsPrec is based).

Monad superclass

The Monad class has an Applicative superclass. You cannot write Monad instances that work for GHC and also for a Haskell 2010 implementation that does not define Applicative.

Extra instances

The following extra instances are defined:

instance Functor ((->) r)
instance Monad ((->) r)
instance Functor ((,) a)
instance Functor (Either a)
instance Monad (Either e)
Multiply-defined array elements not checked

This code fragment should elicit a fatal error, but it does not:

main = print (array (1,1) [(1,2), (1,3)])

GHC’s implementation of array takes the value of an array slot from the last (index,value) pair in the list, and does no checking for duplicates. The reason for this is efficiency, pure and simple.

16.1.1.9. In Prelude support¶
splitAt semantics

Data.List.splitAt is more strict than specified in the Report. Specifically, the Report specifies that

splitAt n xs = (take n xs, drop n xs)

which implies that

splitAt undefined undefined = (undefined, undefined)

but GHC’s implementation is strict in its first argument, so

splitAt undefined [] = undefined
Showing records

The Haskell 2010 definition of Show stipulates that the rendered string should only include parentheses which are necessary to unambiguously parse the result. For historical reasons, Show instances derived by GHC include parentheses around records despite the fact that record syntax binds more tightly than function application; e.g.,

data Hello = Hello { aField :: Int } deriving (Show)

-- GHC produces...
show (Just (Hello {aField=42})) == "Just (Hello {aField=42})"

-- whereas Haskell 2010 calls for...
show (Just (Hello {aField=42})) == "Just Hello {aField=42}"
Reading integers

GHC’s implementation of the Read class for integral types accepts hexadecimal, octal and binary literals (the code in the Haskell 98 report doesn’t). So, for example,

works in GHC.

This is to maintain consistency with the language’s syntax. Haskell98 accepts hexadecimal and octal formats, and GHC2021 accepts binary formats too.

isAlpha

The Haskell 98 definition of isAlpha is:

isAlpha c = isUpper c || isLower c

GHC’s implementation diverges from the Haskell 98 definition in the sense that Unicode alphabetic characters which are neither upper nor lower case will still be identified as alphabetic by isAlpha.

hGetContents

Lazy I/O throws an exception if an error is encountered, in contrast to the Haskell 98 spec which requires that errors are discarded (see Section 21.2.2 of the Haskell 98 report). The exception thrown is the usual IO exception that would be thrown if the failing IO operation was performed in the IO monad, and can be caught by System.IO.Error.catch or Control.Exception.catch.

16.1.1.10. The Foreign Function Interface¶
hs_init(), hs_exit()

The FFI spec requires the implementation to support re-initialising itself after being shut down with hs_exit(), but GHC does not currently support that. See #13693.

16.1.2. GHC’s interpretation of undefined behaviour in Haskell 98 and Haskell 2010¶

This section documents GHC’s take on various issues that are left undefined or implementation specific in Haskell 98.

Char

Following the ISO-10646 standard, maxBound :: Char in GHC is 0x10FFFF.

Int

In GHC the Int type follows the size of an address on the host architecture; in other words it holds 32 bits on a 32-bit machine, and 64-bits on a 64-bit machine.

Arithmetic on Int is unchecked for overflowInt, so all operations on Int happen modulo 2⟨n⟩ where ⟨n⟩ is the size in bits of the Int type.

The fromInteger (and hence also fromIntegral) is a special case when converting to Int. The value of fromIntegral x :: Int is given by taking the lower ⟨n⟩ bits of (abs x), multiplied by the sign of x (in 2’s complement ⟨n⟩-bit arithmetic). This behaviour was chosen so that for example writing 0xffffffff :: Int preserves the bit-pattern in the resulting Int.

Negative literals, such as -3, are specified by (a careful reading of) the Haskell Report as meaning Prelude.negate (Prelude.fromInteger 3). So -2147483648 means negate (fromInteger 2147483648). Since fromInteger takes the lower 32 bits of the representation, fromInteger (2147483648::Integer), computed at type Int is -2147483648::Int. The negate operation then overflows, but it is unchecked, so negate (-2147483648::Int) is just -2147483648. In short, one can write minBound::Int as a literal with the expected meaning (but that is not in general guaranteed).

The fromIntegral function also preserves bit-patterns when converting between the sized integral types (Int8, Int16, Int32, Int64 and the unsigned Word variants), see the modules Data.Int and Data.Word in the library documentation.

Unchecked floating-point arithmetic

Operations on Float and Double numbers are unchecked for overflow, underflow, and other sad occurrences. (note, however, that some architectures trap floating-point overflow and loss-of-precision and report a floating-point exception, probably terminating the program)

Large tuple support

The Haskell Report only requires implementations to provide tuple types and their accompanying standard instances up to size 15. GHC limits the size of tuple types to 64 and provides instances of Eq, Ord, Bounded, Read, Show, and Ix for tuples up to size 15.

16.2. Known bugs or infelicities¶

The bug tracker lists bugs that have been reported in GHC but not yet fixed: see the GHC issue tracker. In addition to those, GHC also has the following known bugs or infelicities. These bugs are more permanent; it is unlikely that any of them will be fixed in the short term.

16.2.1. Bugs in GHC¶ 16.2.2. Bugs in GHCi (the interactive GHC)¶

RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4