GHC says "digits" needs an Int, when it needs an Integral - haskell

As far as I can see, this code snippet should compile without a problem:
import Data.Digits (digits)
-- |convert integer to arbitrary base with specified charset
-- base/radix is charset string length.
-- eg. convert the integer 255 to hex:
-- intToBaseN 255 "0123456789abcdef" = "ff"
numToBaseN :: Integral n => n -> [Char] -> String
numToBaseN num charlst = map (\i -> charlst !! (fromIntegral i)) lst where
lst = digits (length charlst) num
But GHC complains that the num in the lst expression isn't an Int. But the type of digits is
digits :: Integral n => n -> n -> [n]
it doesn't require an Int as an argument, only something that is an Integral, which the type signature of numToBaseN does as well.
!! requires an Int, which is why it is converted using fromIntegral.
What's going on here?
It compiles if I replace num with (fromIntegral num), but then I lose the ability to convert an Integer (ie. arbitrarily large integers).

Both arguments to digits need to have the same type and length charlst has the type Int, so num must also have type Int.
It compiles if I replace num with (fromIntegral num), but then I lose the ability to convert an Integer
If you apply fromIntegral to length charlst instead, it will convert it to whichever type num is, so it'll work the way you want.

Related

fromInteger is a cast?

I'm looking at this, as well as contemplating the whole issue of non-decimal literals, e.g., 1, being just sugar for fromInteger 1 and then I find the type is
λ> :t 1
1 :: Num p => p
This and the statement
An integer literal represents the application of the function
fromInteger to the appropriate value of type Integer.
have me wondering what is really going on. Likewise,
λ> :t 3.149
3.149 :: Fractional p => p
Richard Bird says
A floating-point literal such as 3.149 represents the application of
fromRational to an appropriate rational number. Thus 3.149 :: Fractional a => a
Not understanding what the application of fromRational to an appropriate rational number means. Then he says this is all necessary to be able to add, e.g., 42 + 3.149.
I feel there's a lot going on here that I just don't understand. Like there's too much hand-waving for me. It seems like a cast of an unidentified non-decimal or decimal to specific types, Integer and Rational. So first, why is 1 actually fromInteger 1 internally? I realize every expression must be evaluated as a type, but why is fromInteger and fromRational involved?
Auxillary
So at this page
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): fromIntegral :: (Num b, Integral a) => a -> b
Then comes the example
λ> sqrt 1
1.0
λ> sqrt (1 :: Int)
... error...
λ> sqrt (fromInteger 1)
1.0
λ> :t sqrt 1
sqrt 1 :: Floating a => a
λ> :t sqrt (1 :: Int)
...error...
λ> :t sqrt
sqrt :: Floating a => a -> a
λ> :t sqrt (fromInteger 1)
sqrt (fromInteger 1) :: Floating a => a
So yes, this is a cast, but I don't know the mechanism of how fromI* is doing this --- since technically it's not a cast in a C/C++ sense. All instances of Num must have a fromInteger. It seems like under the hood Haskell is taking whatever you put in and generic-izing it to Integer or Rational, then "giving it back" to the original function, e.g., with sqrt (fromInteger 1) being of type Floating a => a. This is very mysterious to someone prone to over-thinking.
So yes, 1 is a literal, a constant that is polymorphic. It may represent 1 in any type that instantiates Num. The role of fromInteger must be to allowing a value (a cast) to be extracted from an integer constant consistent with what the situation calls for. But this is hand-waving talk at some point. I dont' get how this is actually happening.
Perhaps this will help...
Imagine a language, like Haskell, except that the literal program text 1 represents a term of type Integer with value one, and the literal program text 3.14 represents a term of type Rational with value 3.14. Let's call this language "AnnoyingHaskell".
To be clear, when I say "represents" in the above paragraph, I mean that the AnnoyingHaskell compiler actually compiles those literals into machine code that produces an Integer term whose value is the number 1 in the first case, and a Rational term whose value is the number 3.14 in the second case. An Integer is -- at it's core -- an arbitrary precision integer as implemented by the GMP library, while a Rational is a pair of two Integers, understood to be the numerator and denominator of a rational number. For this particular rational, the two integers would be 157 and 50 (i.e., 157/50=3.14).
AnnoyingHaskell would be... erm... annoying to use. For example, the following expression would not type check:
take 3 "hello"
because 3 is an Integer but take's first argument is an Int. Similarly, the expression:
42 + 3.149
would not type check, because 42 is an Integer and 3.149 is a Rational, and in AnnoyingHaskell, as in Haskell itself, you cannot add an Integer and a Rational.
Because this is annoying, the designers of Haskell made the decision that the literal program text 42 and 3.149 should be treated as if they were the AnnoyingHaskell expressions fromInteger 42 and fromRational 3.149.
The AnnoyingHaskell expression:
fromInteger 42 + fromRational 3.149
does type check. Specifically, the polymorphic function:
fromInteger :: (Num a) => Integer -> a
accepts the AnnoyingHaskell literal 42 :: Integer as its argument, and the resulting subexpression fromInteger 42 has resulting type Num a => a for some fresh type a. Similarly, fromRational 3.149 is of type Fractional b => b for some fresh type b. The + operator unifies these two types into a single type (Num c, Fractional c) => c, but Num c is redundant because Num is a superclass of Fractional, so the whole expression has a polymorphic type:
fromInteger 42 + fromRational 3.149 :: Fractional c => c
That is, this expression can be instantiated at any type with a Fractional constraint. For example. In the Haskell program:
main = print $ 42 + 3.149
which is equivalent to the AnnoyingHaskell program:
main = print $ fromInteger 42 + fromRational 3.149
the usual "defaulting" rules apply, and because the expression passed to the print statement is an unknown type c with a Fractional c constraint, it is defaulted to Double, allowing the program to actually run, computing and printing the desired Double.
If the compiler was awful, this program would run by creating a 42 :: Integer on the heap, calling fromInteger (specialized to fromInteger :: Integer -> Double) to create a 42 :: Double, then create 3.149 :: Rational on the heap, calling fromRational (specialized to fromRational :: Rational -> Double) to create a 3.149 :: Double, and then add them together to create the final answer 45.149 :: Double. Because the compiler isn't so awful, it just creates the number 45.149 :: Double directly.
Perhaps this will help more. One thing you seem to be struggling with is the nature of a value of type Num a => a, like the one produced by fromInteger (1 :: Integer). I think you're somehow imagining that fromInteger "packages" up the 1 :: Integer in a box so it can later be cast by special compiler magic to a 1 :: Int or 1 :: Double.
That's not what's happening.
Consider the following type class:
{-# LANGUAGE FlexibleInstances #-}
class Thing a where
thing :: a
with associated instances:
instance Thing Bool where thing = True
instance Thing Int where thing = 16
instance Thing String where thing = "hello, world"
instance Thing (Int -> String) where thing n = replicate n '*'
and observe the result of running:
main = do
print (thing :: Bool)
print (thing :: Int)
print (thing :: String)
print $ (thing :: Int -> String) 15
Hopefully, you're comfortable enough with type classes that you don't find the output surprising. And presumably you don't think that thing contains some specific, identifiable "thing" that is being "cast" to a Bool, Int, etc. It's simply that thing is a polymorphic value whose definition depends on its type; that's just how type classes work.
Now, consider the similar example:
{-# LANGUAGE FlexibleInstances #-}
import Data.Ratio
import Data.Word
import Unsafe.Coerce
class Three a where
three :: a
-- for base >= 4.10.0.0, can import GHC.Float (castWord64ToDouble)
-- more generally, we can use this unsafe coercion:
castWord64ToDouble :: Word64 -> Double
castWord64ToDouble w = unsafeCoerce w
instance Three Int where
three = length "aaa"
instance Three Double where
three = castWord64ToDouble 0x4008000000000000
instance Three Rational where
three = (6 :: Integer) % (2 :: Integer)
main = do
print (three :: Int)
print (three :: Double)
print (three :: Rational)
print $ take three "abcdef"
print $ (sqrt three :: Double)
Can you see here how three :: Three a => a represents a value that can be used as an Int, Double, or Rational? If you want to think of it as a cast, that's fine, but obviously there's no identifiable single "3" that's packaged up in the value three being cast to different types by compiler magic. It's just that a different definition of three is invoked, depending on the type demanded by the caller.
From here, it's not a big leap to:
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MagicHash #-}
import Data.Ratio
import Data.Word
import Unsafe.Coerce
class MyFromInteger a where
myFromInteger :: Integer -> a
instance MyFromInteger Integer where
myFromInteger x = x
instance MyFromInteger Int where
-- for base >= 4.10.0.0 can use the following:
-- -- Note: data Integer = IS Int | ...
-- myFromInteger (IS i) = I# i
-- myFromInteger _ = error "not supported"
-- to support more GHC versions, we'll just use this extremely
-- dangerous coercion:
myFromInteger i = unsafeCoerce i
instance MyFromInteger Rational where
myFromInteger x = x % (1 :: Integer)
main = do
print (myFromInteger 1 :: Integer)
print (myFromInteger 2 :: Int)
print (myFromInteger 3 :: Rational)
print $ take (myFromInteger 4) "abcdef"
Conceptually, the base library's fromInteger (1 :: Integer) :: Num a => a is no different than this code's myFromInteger (1 :: Integer) :: MyFromInteger a => a, except that the implementations are better and more types have instances.
See, it's not that the expression fromInteger (1 :: Integer) boxes up a 1 :: Integer into a package of type Num a => a for later casting. It's that the type context for this expression causes dispatch to an appropriate Num type class instance, and a different definition of fromInteger is invoked, depending on the required type. That fromInteger function is always called with argument 1 :: Integer, but the returned type depends on the context, and the code invoked by the fromInteger call (i.e., the definition of fromInteger used) to convert or "cast" the argument 1 :: Integer to a "one" value of the desired type depends on which return type is demanded.
And, to go a step further, as long as we take care of a technical detail by turning off the monomorphism restriction, we can write:
{-# LANGUAGE NoMonomorphismRestriction #-}
main = do
let two = myFromInteger 2
print (two :: Integer)
print (two :: Int)
print (two :: Rational)
This may look strange, but just as myFromInteger 2 is an expression of type Num a => a whose final value is produced using a definition of myFromInteger, depending on what type is ultimately demanded, the expression two is also an expression of type Num a => a whose final value is produced using a definition of myFromInteger that depends on what type is ultimately demanded, even though the literal program text myFromInteger does not appear in the expression two. Moreover, continuing with:
let four = two + two
print (four :: Integer)
print (four :: Int)
print (four :: Rational)
the expression four of type Num a => a will produce a final value that depends on the definition of myFromInteger and the definition of (+) that are determined by the finally demanded return type.
In other words, rather than thinking of four as a packaged 4 :: Integer that's going to be cast to various types, you need to think of four as completely equivalent to its full definition:
four = myFromInteger 2 + myFromInteger 2
with a final value that will be determined by using the definitions of myFromInteger and (+) that are appropriate for whatever type is demanded of four, whether its four :: Integer or four :: Rational.
The same goes for sqrt (fromIntegral 1) After:
x = sqrt (fromIntegral (1 :: Integer))
the value of x :: Floating a => a is equivalent to the full expression:
sqrt (fromIntegral (1 :: Integer))
and every place it is is used, it will be calculated using definitions of sqrt and fromIntegral determined by the Floating and Num instances for the final type demanded.
Here's all the code in one file, testing with GHC 8.2.2 and 9.2.4.
{-# LANGUAGE Haskell98 #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
import Data.Ratio
import GHC.Num
import GHC.Int
import GHC.Float (castWord64ToDouble)
class Thing a where
thing :: a
instance Thing Bool where thing = True
instance Thing Int where thing = 16
instance Thing String where thing = "hello, world"
instance Thing (Int -> String) where thing n = replicate n '*'
class Three a where
three :: a
instance Three Int where
three = length "aaa"
instance Three Double where
three = castWord64ToDouble 0x4008000000000000
instance Three Rational where
three = (6 :: Integer) % (2 :: Integer)
class MyFromInteger a where
myFromInteger :: Integer -> a
instance MyFromInteger Integer where
myFromInteger x = x
instance MyFromInteger Int where
-- Note: data Integer = IS Int | ...
myFromInteger (IS i) = I# i
myFromInteger _ = error "not supported"
instance MyFromInteger Rational where
myFromInteger x = x % (1 :: Integer)
main = do
print (thing :: Bool)
print (thing :: Int)
print (thing :: String)
print $ (thing :: Int -> String) 15
print (three :: Int)
print (three :: Double)
print (three :: Rational)
print $ take three "abcdef"
print $ (sqrt three :: Double)
print (myFromInteger 1 :: Integer)
print (myFromInteger 2 :: Int)
print (myFromInteger 3 :: Rational)
print $ take (myFromInteger 4) "abcdef"
let two = myFromInteger 2
print (two :: Integer)
print (two :: Int)
print (two :: Rational)
let four = two + two
print (four :: Integer)
print (four :: Int)
print (four :: Rational)

Why does ghc warn that ^2 requires "defaulting the constraint to type 'Integer'?

If I compile the following source file with ghc -Wall:
main = putStr . show $ squareOfSum 5
squareOfSum :: Integral a => a -> a
squareOfSum n = (^2) $ sum [1..n]
I get:
powerTypes.hs:4:18: warning: [-Wtype-defaults]
• Defaulting the following constraints to type ‘Integer’
(Integral b0) arising from a use of ‘^’ at powerTypes.hs:4:18-19
(Num b0) arising from the literal ‘2’ at powerTypes.hs:4:19
• In the expression: (^ 2)
In the expression: (^ 2) $ sum [1 .. n]
In an equation for ‘squareOfSum’:
squareOfSum n = (^ 2) $ sum [1 .. n]
|
4 | squareOfSum n = (^2) $ sum [1..n]
| ^^
I understand that the type of (^) is:
Prelude> :t (^)
(^) :: (Integral b, Num a) => a -> b -> a
which means it works for any a^b provided a is a Num and b is an Integral. I also understand the type hierarchy to be:
Num --> Integral --> Int or Integer
where --> denotes "includes" and the first two are typeclasses while the last two are types.
Why does ghc not conclusively infer that 2 is an Int, instead of "defaulting the constraints to Integer". Why is ghc defaulting anything? Is replacing 2 with 2 :: Int a good way to resolve this warning?
In Haskell, numeric literals have a polymorphic type
2 :: Num a => a
This means that the expression 2 can be used to generate a value in any numeric type. For instance, all these expression type-check:
2 :: Int
2 :: Integer
2 :: Float
2 :: Double
2 :: MyCustomTypeForWhichIDefinedANumInstance
Technically, each time we use 2 we would have to write 2 :: T to choose the actual numeric type T we want. Fortunately, this is often not needed since type inference can frequently deduce T from the context. E.g.,
foo :: Int -> Int
foo x = x + 2
Here, x is an Int because of the type annotation, and + requires both operands to have the same type, hence Haskell infers 2 :: Int. Technically, this is because (+) has type
(+) :: Num a => a -> a -> a
Sometimes, however, type inference can not deduce T from the context. Consider this example involving a custom type class:
class C a where bar :: a -> String
instance C Int where bar x = "Int: " ++ show x
instance C Integer where bar x = "Integer: " ++ show x
test :: String
test = bar 2
What is the value of test? Well, if 2 is an Int, then we have test = "Int: 2". If it is an Integer, then we have test = "Integer: 2". If it's another numeric type T, we can not find an instance for C T.
This code is inherently ambiguous. In such a case, Haskell mandates that numeric types that can not be deduced are defaulted to Integer (the programmer can change this default to another type, but it's not relevant now). Hence we have test = "Integer: 2".
While this mechanism makes our code type check, it might cause an unintended result: for all we know, the programmer might have wanted 2 :: Int instead. Because of this, GHC chooses the default, but warns about it.
In your code, (^) can work with any Integral type for the exponent. But, in principle, x ^ (2::Int) and x ^ (2::Integer) could lead to different results. We know this is not the case since we know the semantics of (^), but for the compiler (^) is only a random function with that type, which could behave differently on Int and Integer. Consider, e.g.,
a ^ n = if n + 3000000000 < 0 then 0 else 1
When n = 2, if we use n :: Int the if guard could be true on a 32 bit system. This is not the case when using n :: Integer which never overflows.
The standard solution, in these cases, is to resolve the warning using something like x ^ (2 :: Int).

why is this snippet valid with an explicit value, but invalid as a function?

I'm trying to work a problem where I need to calculate the "small" divisors of an integer. I'm just bruteforcing through all numbers up to the square root of the given number, so to get the divisors of 10 I'd write:
[k|k<-[1...floor(sqrt 10)],rem 10 k<1]
This seems to work well. But as soon as I plug this in a function
f n=[k|k<-[1...floor(sqrt n)],rem n k<1]
And actually call this function, I do get an error
f 10
No instance for (Floating t0) arising from a use of `it'
The type variable `t0' is ambiguous
Note: there are several potential instances:
instance Floating Double -- Defined in `GHC.Float'
instance Floating Float -- Defined in `GHC.Float'
In the first argument of `print', namely `it'
In a stmt of an interactive GHCi command: print it
As far as I undrestand the actual print function that prints the result to the console is causing trouble, but I cannot find out what is wrong. It says the type is ambiguous, but the function can clearly only return a list of integers. Then again I checked the type, and it the (inferred) type of f is
f :: (Floating t, Integral t, RealFrac t) => t -> [t]
I can understand that fshould be able to accept any real numerical value, but can anyone explain why the return type should be anything else than Integral or int?
[k|k<-[1...floor(sqrt 10)],rem 10 k<1]
this works because the first 10 is not the same as the latter one - to see this, we need the type signature of your functions:
sqrt :: Floating a => a -> a
rem :: Integral a => a -> a -> a
so the first one means that it works for stuff that have a floating point representation - a.k.a. Float, Double ..., and the second one works for Int, Integer (bigint), Word8 (unsigned 8bit integers)...
so for the 10 in sqrt 10 the compiler says - ahh this is a floating point number, null problemo, and for the 10 in rem 10 k, ahh this is an integer like number, null problemo as well.
But when you bundle them up in a function - you are saying n has to be a floating point and an integral number, the compiler knows no such thing and - complains.
So what do we do to fix that (and a side note ranges in haskell are indicated by .. not ...!). So let us start by taking a concrete solution and generalize it.
f :: Int -> [Int]
f n = [k|k <- [1..n'],rem n k < 1]
where n' = floor $ sqrt $ fromIntegral n
the neccessary part was converting the Int to a floating point number. But if you are putting that in a library all your users need to stick with using Int which is okay, but far from ideal - so how do we generalize (as promised)? We use GHCi to do that for us, using a lazy language we ourselves tend to be lazy as well.
We start by commenting out the type-signature
-- f :: Int -> [Int]
f n = [k|k <- [1..n'],rem n k < 1]
where n' = floor $ sqrt $ fromIntegral n
$> ghci MyLib.hs
....
MyLib > :type f
f :: Integral a => a -> [a]
then we can take this and put it into the library and if someone worked with Word8 or Integer that would work as well.
Another solution would be to use rem (floor n) k < 1 and have
f :: Floating a, Integral b => a -> [b]
as the type, but that would be kind of awkward.

How do I cast from Integer to Fractional

Let's say I have the following Haskell type description:
divide_by_hundred :: Integer -> IO()
divide_by_hundred n = print(n/100)
Why is it that when I attempt to run this through ghc I get:
No instance for (Fractional Integer) arising from a use of `/'
Possible fix: add an instance declaration for (Fractional Integer)
In the first argument of `print', namely `(n / 100)'
In the expression: print (n / 100)
In an equation for `divide_by_hundred':
divide_by_hundred n = print (n / 100)
By running :t (/)
I get:
(/) :: Fractional a => a -> a -> a
which, to me, suggests that the (/) can take any Num that can be expressed as fractional (which I was under the impression should include Integer, though I am unsure as how to verify this), as long as both inputs to / are of the same type.
This is clearly not accurate. Why? And how would I write a simple function to divide an Integer by 100?
Haskell likes to keep to the mathematically accepted meaning of operators. / should be the inverse of multiplication, but e.g. 5 / 4 * 4 couldn't possibly yield 5 for a Fractional Integer instance1.
So if you actually mean to do truncated integer division, the language forces you2 to make that explicit by using div or quot. OTOH, if you actually want the result as a fraction, you can use / fine, but you first need to convert to a type with a Fractional instance. For instance,
Prelude> let x = 5
Prelude> :t x
x :: Integer
Prelude> let y = fromIntegral x / 100
Prelude> y
5.0e-2
Prelude> :t y
y :: Double
Note that GHCi has selected the Double instance here because that's the simples default; you could also do
Prelude> let y' = fromIntegral x / 100 :: Rational
Prelude> y'
1 % 20
1Strictly speaking, this inverse identity doesn't quite hold for the Double instance either because of floating-point glitches, but there it's true at least approximately.
2Actually, not the language but the standard libraries. You could define
instance Fractional Integer where
(/) = div
yourself, then your original code would work just fine. Only, it's a bad idea!
You can use div for integer division:
div :: Integral a => a -> a -> a
Or you can convert your integers to fractionals using fromIntegral:
fromIntegral :: (Integral a, Num b) => a -> b
So in essence:
divide_by_hundred :: Integer -> IO()
divide_by_hundred n = print $ fromIntegral n / 100
Integers do not implement Fractional, which you can see in the manual.

Is it square check

I am trying to write function to check if the argument is square of integer:
isSquare :: Int -> Bool
isSquare x = truncate(sqrt(x)) * truncate(sqrt(x)) == x
When I loading the function I get the error:
Prelude> :load "some.hs"
[1 of 1] Compiling Main ( some.hs, interpreted )
some.hs:2:13:
No instance for (RealFrac Int)
arising from a use of `truncate' at some.hs:2:13-29
Possible fix: add an instance declaration for (RealFrac Int)
In the first argument of `(*)', namely `truncate (sqrt (x))'
In the first argument of `(==)', namely
`truncate (sqrt (x)) * truncate (sqrt (x))'
In the expression: truncate (sqrt (x)) * truncate (sqrt (x)) == x
some.hs:2:22:
No instance for (Floating Int)
arising from a use of `sqrt' at some.hs:2:22-28
Possible fix: add an instance declaration for (Floating Int)
In the first argument of `truncate', namely `(sqrt (x))'
In the first argument of `(*)', namely `truncate (sqrt (x))'
In the first argument of `(==)', namely
`truncate (sqrt (x)) * truncate (sqrt (x))'
Failed, modules loaded: none.
But if i try to execute:
Prelude> truncate(sqrt(9))*truncate(sqrt(9))==9
True
all is fine.
Why I get the error and how to fix it ?
You're getting the errors because of type mismatches. The type of sqrt is sqrt :: Floating a => a -> a, and the type of truncate is truncate :: (RealFrac a, Integral b) => a -> b. The former says that sqrt takes as input any floating-point number, and returns one of the same type as output; the latter says it can truncate any real fractional number1 into any integral number. However, you assert that x is an Int, and an Int isn't a floating-point number. Thus, the second error: "No instance for (Floating Int) arising from a use of `sqrt'". This says that because of sqrt x, it wanted Int to be a floating-point number, but there's no definition for that. Your first error is similar: since sqrt :: Floating a => a -> a, its output is the same as its input, so you're trying to call truncate on an integer. This of course makes no sense, since Int is not a RealFrac, and that's why you get the first error. Fixing this is easy:
isSquare :: Int -> Bool
isSquare x = let x' = truncate $ sqrt (fromIntegral x :: Double) in x'*x' == x
The fromIntegral function has the type fromIntegral :: (Integral a, Num b) => a -> b; it can convert any integral number into any number at all. This is why we need to tell Haskell that we want it to produce a Double; it'd default to that anyway, but it's nice to be clear (though not necessary). Double is an instance both of Floating and RealFrac, so you can sqrt and truncate it. I also rearranged your code a little; the way it is up there is how I'd write it, since this way we only compute the truncation and sqrt once. Also, note that if you remove the type signature, Haskell will infer the more general type isSquare :: Integral a => a -> Bool, since you never assume that x is precisely an Int.
The reason that truncate(sqrt(9))*truncate(sqrt(9))==9 successfully returned True is because of the type of 9. You can ask GHCi to tell you this:
Prelude> :t 9
9 :: (Num t) => t
In Haskell, all integral numeric literals have the type Num t => t (9.0, or any number with a decimal point, has the type Fractional t => t). This means that they can be any kind of number at all, which is a good thing. Otherwise, 9 would have to just be an Int or Integer, and defining new number types—or even using both Int and Integer!2—would be a royal pain. Thus, when you write truncate(sqrt(9)), GHCi determines that 9 must be an instance of Floating (from sqrt) and RealFrac (from truncate), which it defaults to Double, making everything work. This defaulting is standard behavior for numeric types (it's why you could leave out the :: Double in my definition of isSquare), though not for anything else (except in GHCi, which extends it for convenience). Since 9 isn't just an Int, but x is, you don't need to convert 9, but you do need to convert x.
1: The difference between Floating and RealFrac is that, for instance, Complex Double is an instance of Floating but not RealFrac, and Rational is an instance of RealFrac but not Floating. Float and Double are instances of both.
2: In case you haven't come across this, the difference is that Int is finite-precision, and Integer is arbitrary-precision.
You're treating integers as floats. Hence, the types don't match.
Use fromIntegral:
isSquare :: Int -> Bool
isSquare n = truncate(sqrt(x)) * truncate(sqrt(x)) == n
where x = fromIntegral n
Not all that efficient but a cute way of determining if a number is a square, using integer arithmetic only:
isSquare x = x == head (dropWhile (< x) squares)
where squares = scanl1 (+) [1,3..]

Resources