Haskell multiply Int and real number

試著忘記壹切 提交于 2019-11-30 22:43:12

There is a function, fromIntegral, which will convert an integral number to any other numeric type. So you can do:

result :: (Integral n, Num m) => n -> m -> m
result val coefficient = fromIntegral val * coefficient

Or, in point-free style:

result = (*) . fromIntegral

Update about updated question(@Drew)

Consider this code:

coefficient :: (Num a) => a
coefficient = 1.0

This is invalid on it's own, as follows. Because 1.0 is a literal for a fractional number (not a whole integer), then GHC can only encode it as any type which is capable of representing fractional numbers (forall a. Fractional a => a). However, you have specified that it must be valid for any numeric type (forall a. Num a => a). Some numeric types (e.g. Integer) cannot represent fractional values, and are not instances of Fractional (rightly so), so this cannot typecheck. You can fix this as follows:

coefficient :: (Fractional a) => a
coefficient = 2.0

Here GHC can infer the type, and coefficient works fine. It is important to note, that Fractional is a subclass of Num, so everything that is a Fractional must also be a Num. If we look at the function in the first part of my answer, coefficient is only required to be a Num type (as we only use it with (*)), so we can use this definition of coefficient in place of that parameter. Your problem occurs for exactly the same reason.

result :: (Num a) => a
result = coefficient * fromIntegral val

Again, the result of this function must be of the same type as coefficient. As coefficient cannot be any Num type, but only a fractional type, we need to change this to:

result :: (Fractional a) => a
result = coefficient * fromIntegral val

And then that should typecheck. @singpolyma is right that your original error was partly to do with the monomorphism restriction, but you just needed to make the type signatures slightly more specific. If you want it to work with (Num a) => a, then coefficient must be a whole number (e.g. 1).

Update about GHCi (@Marcin)

For using this in GHCi, I would suggest letting GHCi infer the type. If in this case you type (in GHCi):

let result val coefficient = fromIntegral val * coefficient

Then GHCi will correctly infer the type of the result. You can ask GHCi what type it thinks something is using the ':t' command:

Prelude> :t result
result :: (Integral a1, Num a) => a1 -> a -> a

If you must have an explicit type signature you can do:

let result = (\val coefficient -> fromIntegral val * coefficient) :: (Integral a, Num b) => a -> b -> b

To try and have an explicit type, but GHCi will make this monomorphic:

Prelude> :t result
result :: Integer -> Integer -> Integer

Which we don't want (this is because the type annotation refers to the value of the lambda expression, not the declaration of result). I don't know how to get the explicit type to work here either, so maybe someone more knowledgeable than us can answer :P

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!