September 16, 2026

Haskell for Hobos -- Int64

All kinds of weird issues erupt if you try to use Int64. You cannot mix Int and Int64 in expressions. You can use "fromIntegral" as you would use a cast in the C language to get Int64 values to work with Int values.

Some Haskell modules will unexpectedly hand you Int64 values, and you have to use fromIntegral to tame the mess. I suppose they are trying to move towards the future, but documentation still shows them returning Int.
As an example:

import Data.Int (Int64)

give :: Int64
give = 5

dog :: Int
dog = 9

main = putStrLn $ show $ give + dog
Gives the dreaded error:
Couldn't match expected type ‘Int64’ with actual type ‘Int’

I got strange errors when I did this:

give :: Int64
	give = 5
It turned out that the problem was the indentation, but I got this error:
Expected kind ‘k0 -> *’, but ‘Int64’ has kind ‘*’
It will take a real guru to explain why indentation caused this, and the error message is no help whatsoever.

There is also Word64 which is an unsigned 64 bit value.

Trouble in RWH chapter 10

Here is the offending code:
getBytes :: Int -> L.ByteString -> Maybe (L.ByteString, L.ByteString)
--getBytes n str = let count = fromIntegral n
getBytes n str = let count = n
                     both@(prefix,_) = L.splitAt count str
                 in if L.length prefix < count
                    then Nothing
                    else Just both
In the above, I have commented out the line that makes things work. I have no Int64 declarations anywhere in my code. Once I remove the "fromIntegral" I get the same error twice:
    • Couldn't match expected type ‘GHC.Internal.Int.Int64’
                  with actual type ‘Int’
    • In the first argument of ‘L8.splitAt’, namely ‘count’
	  In the expression: L8.splitAt count str
	• In the second argument of ‘(<)’, namely ‘count’
      In the expression: L8.length prefix < count
It certainly looks like L8.splitAt expects an Int64 and that L8.length is yielding an Int64.

Indeed, when I dig up the API documention for Data.ByteString.Lazy.Char8 and find "length", I see the types:

splitAt :: Int64 -> ByteString -> (ByteString, ByteString)
length :: ByteString -> Int64
So the mystery is solved. The next question is how "fromIntegral" works. It seems to just override the Haskell type system and allow any integer type to work with any other. See this: It says, "The workhorse for converting from integral types is fromIntegral, which will convert from any Integral type into any Numeric type (which includes Int, Integer, Rational, and Double."

Int64 is not explicitly mentioned, but apparently it is an eligible target type as well. It seems (along with other functions mentioned in the above article) to be the duct tape of type conversion in Haskell.


Have any comments? Questions? Drop me a line!

Tom's software pages / tom@mmto.org