(*) :: Num a => a -> a -> a means you can pick any type a you like that is a member of Num, and * can be a function that takes two arguments of that type and returns a result of the same type.
The way type classes work, for each type that is a member of Num a separate implementation of * must be supplied. So there is one function that is (*) :: Integer -> Integer -> Integer, another that is Double -> Double -> Double, another that is Ratio Word32 -> Ratio Word32 -> Ratio Word32, etc, etc. * can be instantiated as any of those separate functions.
Similarly, (/) :: Fractional a => a -> a -> a means you can pick any type a, but here it has to be a member of the Fractional type class, which is more restrictive. Double is a member of Fractional, so there is a (/) :: Double -> Double -> Double function. Integer is just not a member of Fractional, so there is no (/) :: Integer -> Integer -> Integer function.
The reason Integer is not a member of Fractional is that mathematical division of integers simply doesn't result in an integer. You need a type that supports fractional numbers between the integers in order for division to make much sense. There are different operations like div and quot that you can perform on integers, and so they work on types like Integer and Int. If you want one of those operations, you should ask for it, not ask for / and expect it to give you a different operation when you use it on integers. Not least because how would it know whether div or quot is what you think of as "the closest thing to division I can do with integers"? And if you have an Int, Integer, or similar, and you want to translate it to a fractional number so you can do division with it and get a fractional result, then you'll need to use a translation function like fromIntegral; Haskell will not magically insert this for you, but it has all the translation functions and they work just fine.
Note that there is no conversion going on when you call *; it is not that * is happy to convert argument in ways that / is not. The Int version of * requires that you provide it with two Int arguments, the Double version requires that you provide it with two Double arguments, etc. If you call the Double version of * but pass it an Int, it will not convert the Int to a Double: you will get a type error.
New Haskellers often think there must be conversion because they can evaluate expressions like 3.2 * 7, and how else could that work?
In several other popular languages what happens here is that the language implementation says that 3.2 is a floating point number and 7 is an integer, and - like in Haskell - multiplication can only be evaluated with two arguments of the same type. So the language implementation silently inserts some code to translate the integer to the floating point type; what you get is actually something like 3.2 * (floatFromInt 7). But just because that is how other languages handle simple arithmetic expressions doesn't make it the only way, and you would do very well to find out how Haskell (or any other language you start learning) actually handles these expressions when you start learning the language rather than assuming it must be like it is any other language.
In Haskell, the compiler doesn't start by assuming numeric literals like 3.2 or 7 are any particular type. Haskell is more flexible. Instead any integer-like number in the source code can be read as a literal for any numeric type (any type in Num), while a decimal-point number in the source code can be read as a literal for any type in Fractional. Haskell figures out what what version of * is being called by looking at both the context it is used in (the code that consumes the result) as well as the arguments. If any one of those things forces a single type, then both arguments as well as the result must be able to be that single type.
So in cases like 3.2 * 7 it is likely that how the result is used will determine what type the result must be, which in turn determines what the type of * is in that expression, which in turn determines how each of the numeric literals are read. Both will be read in as literals for that same type1. In this case we can even determine that 7 is definitely not Int, or Integer, or anything similar, since those types do not have Fractional instances and the type used must be a Fractional one in order for one of the arguments to use a 3.2 literal containing a decimal point.
1. Of course what "being read in as a literal for any numeric type" actually means is that an integer literal makes Haskell create an Integer and then the fromInteger :: Num a => Integer -> a function from the appropriate type's Num instance can build the "real" value from the Integer. Similarly the decimal-point literals are initially read as a value of type Rational and then the fromRational :: Fractional a => Rational -> a function is used to build the real value.
So if you're being very picky and/or technical, you can argue that 3.2 is in fact always a literal for the fixed type Rational and then the conversion function fromRational is always applied. That is not incorrect, but I view it as an implementation strategy for the concept "3.2 is a literal for any Fractional type". The application of the function will almost always be inlined away at compile time anyway, so at runtime there will only be the values of the final desired type.
I think this point of view is more helpful for new Haskellers precisely because so many get confused expecting automatic type conversion between integers and floating point types to happen as they do in other languages, and that most definitely is not the case; in those other languages that would happen with variables of integral types as well. This form of conversion that Haskell has is only to do with literals, and it's rather different because the fromRational (or fromInteger) translator is always called when you use a literal, it has nothing to do with promoting a real runtime value of one type to match the type of another operand.