Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell, multiplying Int and Float within a function

Tags:

types

haskell

Why is it that in ghci I can enter:

5.0 * (3 - 1) > 10.0 

But if I try and create a function in a .hs file and load it in:

test :: Float -> Int -> Int -> Float test a b c = a * (b - c) 

I am hit with an error? "Couldnt match expected type 'Float' against inferred type 'Int'? And how can I write a function that takes in one floating point and 2 integer arguments and performs the above operation on them?

I am using ghci v6.12.1 if that makes a difference...

like image 725
Sam Coulter Avatar asked Sep 26 '13 03:09

Sam Coulter


People also ask

Can you multiply a float and an Int?

The result of multiplying a float and an integer is always going to be a float.

What happens if you multiply a float by an Int?

The result of the multiplication of a float and an int is a float . Besides that, it will get promoted to double when passing to printf . You need a %a , %e , %f or %g format. The %d format is used to print int types.

What does double mean in Haskell?

Double is the double-precision floating point type, a good choice for real numbers in the vast majority of cases. (Haskell also has Float , the single-precision counterpart of Double , which is usually less attractive due to further loss of precision.)

Can you multiply float and Int in Python?

1. Converting float to integer. The multiplication between float and string is not supported in python. But, to avoid the error from being thrown, we can try converting the given integer value to a string value.


1 Answers

Numeric literals (i.e. just typing a number in Haskell code) are not some fixed type. They are polymorphic. They need to be evaluated in some context that requires them to have a concrete type.

So the expression 5.0 * (3 - 1) is not multiplying an Int by a Float. 5.0 has to be some Fractional type, 3 and 1 are each some Num type. 3 - 1 means that the 3 and the 1 both have to be the same Num type, but we still don't (yet) have any more constraints about which particular one it is; the result of the subtraction is the same type.

The * means both arguments have to be the same type, and the result will be the same type too. Since 5.0 is some Fractional type, the (3 - 1) must be too. We already knew that 3, 1, and (3 - 1) had to be some Num type but all Fractional types are also Num types, so this requirements are not in conflict.

The end result is that the whole expression 5.0 * (3 - 1) is some type that is Fractional, and the 5.0, 3, and 1 are all the same type. You can use the :t command in GHCi to see this:

Prelude> :t 5.0 * (3 - 1) 5.0 * (3 - 1) :: Fractional a => a 

But to actually evaluate that expression, we need to do so for some concrete type. If we were evaluating this and passing it to some function that required Float, Double, or some other particular Fractional type then Haskell would pick that one. If we just evaluate the expression with no other context requiring it to be a particular type, Haskell has some defaulting rules to automatically choose one for you (if the defaulting rules don't apply it will instead give you a type error about ambiguous type variables).

Prelude> 5.0 * (3 - 1) 10.0 Prelude> :t it it :: Double 

Above I've evaluated 5.0 * (3 - 1), then asked for the type of the magic it variable which GHCi always binds to the last value it evaluated. This tells me that GHCi has defaulted my Fractional a => a type to just Double, in order to compute that the value of the expression was 10.0. In doing that evaluation, it only ever multipled (and subtracted) Doubles, it never multiplied a Double by an Int.


Now, that's what's going on when you attempt to multiple numeric literals that look like they might be of different types. But your test function isn't multiplying literals, it's multiplying variables of particular known types. In Haskell you can't multiply an Int by a Float because the * operator has type Num a => a -> a -> a - it takes two values of the same numeric type and gives you a result that is that type. You can multiply an Int by an Int to get an Int, or a Float by a Float to get a Float. You can't multiply an Int by a Float to get a ???.

Other languages support this sort of operation only by implicitly inserting calls to conversion functions under some circumstances. Haskell never implicitly converts between types, but it has the conversion functions. You just need to call them explicitly if you want them to be called. This would do the trick:

test :: Float -> Int -> Int -> Float test a b c = a * fromIntegral (b - c) 
like image 124
Ben Avatar answered Sep 21 '22 13:09

Ben