build-depends
section place an upper bound on base
?Int
and what is Integer
?Float
value cannot be represented by Int
?This will eventually become Frequently Asked Questions once the questions have been asked more than once each!
My hand-wavy answer to this was "It doesn't matter" since referential transparency guarantees that whether the inner computation was performed more than once cannot be observed by outside users. But, of course, this is not really true since more than one computation could incur a time or performance overhead that could be observed by the end user.
My claim is that Haskell programming language specification does not go into this and an implementation is free to deal with this however it sees fit.
I will look into the details of this and get back to you when I have a more satisfactory answer.
Here's a good source.
build-depends
section place an upper bound on base
?Hackage (the Haskell package repository) prefers to use package versioning policy for packages, but does not attempt to enforce it. Anyway, the gist of this policy is that versions of packages, including base
, should be compatible if they have the same major version number. Moving forward to base
with a newer major version is likely to require nontrivial changes to a project's dependencies and/or source code.
I believe that the Haskell specification doesn't, to the best of my knowledge, mandate whether a conformant Haskell implementation should compile or interpret code. Neither does mandate whether the implementation should generate native code or an intermediate language. We'll be using GHC—the Glasgow Haskell Compiler—which is a compiler and emits native code (and other kinds of output with different backends). This is true even of GHCi, the REPL, which compiles code incrementally using the GHC API.
While performing interactive evaluation, input can split across multiple lines using the :{
and :}
delimiters:
λ> :{
λ| let { g op n [] = n
λ| ; g op n (h:t) = h `op` g op n t
λ| }
λ| :}
λ> g (*) 1 [1..3]
6
This can be done using the :sprint
command:
λ> a = 5 + 6
λ> :t a
a :: Num a => a
λ> :sprint a
a = _
λ> a
11
λ> :sprint a
a = _
λ> b = (5 + 6) :: Int
λ> :t b
b :: Int
λ> :sprint b
b = _
λ> b
11
λ> :sprint b
b = 11
λ> xs = [0 ..]
λ> :t xs
xs :: (Num t, Enum t) => [t]
λ> :sprint xs
xs = _
λ> head xs
0
λ> :sprint xs
xs = _
λ> ys = [0 ..] :: [Int]
λ> :t ys
ys :: [Int]
λ> :sprint ys
ys = _
λ> head ys
0
λ> :sprint ys
ys = 0 : _
Notes:
_
a
and xs
are polymorphic types and will always show up as _
a
and xs
will demonstrate partial or full evaluation using :sprint
b
and ys
are monomorphic (i.e. concrete) types and demonstrate partial and full evaluationInt
and what is Integer
?We'll talk about this in later session. For now, all you need to know is that Int
is a machine integer (akin to int
in C++) while Integer
is an arbitrary precision or "mathematical" integer. Both provide instances of the Num
type class.
Float
value cannot be represented by Int
?Automatic conversions between numeric types is unsupported. This is likely to remain the case forever. Here's what happens when we try to convert floating-point values that are unrepresentable as integers:
Let's define infinity
be reading its string represention:
λ> infinity = read "Infinity" :: Float
λ> infinity
Infinity
λ> :t infinity
infinity :: Float
And, similarly, nan
:
λ> nan = read "NaN" :: Float
λ> nan
NaN
> :t nan
nan :: Float
Let's convert these to Integer
and Int
:
> round infinity :: Integer
340282366920938463463374607431768211456
λ> round nan :: Integer
-510423550381407695195061911147652317184
λ> round infinity :: Int
0
λ> round nan :: Int
0
I was somewhat disappointed by some of these behaviours to be honest. However, I expect that this is roughly equivalent to how a C++ compiler would behave. If these special values, and other unrepresentable values, are important to the correct running of the program, the RealFloat
type class offers the full array of helper functions such as isNaN
and isInfinite
that you'd expect.
GHCi offers :back
, :forward
, :trace
, :history
commands. There is also the ~/.ghc/ghci_history
file that retains a log of your GHCi commands.