Compiling the following program:
main = print (sqrt (-7))
On OSX Yosemite, LLVM version 3.4.2, target x86_64-apple-darwin14.0.0, GHC 7.8.4 produces two different results, depending on llvm use:
apple1$ ghc -fforce-recomp a.hs -o a; ./a [1 of 1] Compiling Main ( a.hs, a.o ) Linking a ... NaN apple1$ ghc -fforce-recomp -fllvm a.hs -o a; ./a [1 of 1] Compiling Main ( a.hs, a.o ) Linking a ... 0.0
Why this happens?
Haskell is different in two ways: Values are immutable by default, and mutability must be explicitly indicated with a variable type. Mutating a mutable variable is considered a side effect, and that mutable is tracked by the type system.
The compiler (written in Haskell), translates Haskell to C, assembly, LLVM bitcode and other formats. The strategy it uses is described best here: Implementing lazy functional languages on stock hardware:the Spineless Tagless G-machine.
Open a command window and navigate to the directory where you want to keep your Haskell source files. Run Haskell by typing ghci or ghci MyFile. hs. (The "i" in "GHCi" stands for "interactive", as opposed to compiling and producing an executable file.)
Unlike Python, Ruby, JavaScript, Lua, and other interpreted languages, Haskell is compiled ahead-of-time, directly to native machine code. The compiler (GHC) is remarkably good at optimization and generating efficient executables.
Haskell has a very good type system. Algebraic data types allow for types like Maybe and Either and we can use values of those types to represent results that may be there or not. In C, returning, say, -1 on failure is completely a matter of convention. It only has special meaning to humans.
Do not despair, all is not lost. It turns out that Haskell actually has a really clever system for dealing with functions that have side-effects that neatly separates the part of our program that is pure and the part of our program that is impure, which does all the dirty work like talking to the keyboard and the screen.
Edit: I see the question comments have the source, and others have also commented on Eclipse and Putty not being C compilers. Generally speaking, the same program producing different output with different compilers is a sign that you’ve run into undefined behavior — typically this means that you’ve done something wrong.
The type is different from just plain a -> b and if we try to use those two functions interchangeably, the compiler will complain at us. Despite having expressive types that support failed computations, Haskell still has support for exceptions, because they make more sense in I/O contexts.
(Question answered in the comments. Converted to a community wiki answer. See Question with no answers, but issue solved in the comments (or extended in chat) )
@leftaroundabout wrote:
I would consider it a bug, though it might well have been acceptable according to some specification. LLVM evidently fired some optimisation here which assumes non-negative arguments, making √(-7) undefined behaviour.
@Ed'ka wrote:
Probably related: LLVM bug 21048
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With