Haskell Multiplies Int and Real

I have

coefficient :: ??????? coefficient = 1.0 

and

 val :: Int 

and i would like to do

 result :: ??????? result val coefficient = val * coefficient 

What types of signatures and conversion functions do I need to make this work? What should I do in addition to this if I want to be able to generalize val to any kind of Num?

It:

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

gives me this warning for the compiler:

 Could not deduce (a ~ Double) from the context (Num a) bound by the type signature for result :: Num a => a at Move.hs:17:1-41 `a' is a rigid type variable bound by the type signature for result :: Num a => a at Move.hs:17:1 In the first argument of `(*)', namely `coefficient' In the expression: coefficient * (fromIntegral val) In an equation for `result': result = coefficient * (fromIntegral val) 

I know that this is not what I asked initially, I made some mistakes when disinfecting my code.

Now with the type for the coefficient:

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

received error:

 Could not deduce (Fractional a) arising from the literal `1.0' from the context (Num a) bound by the type signature for coefficient :: Num a => a at Move.hs:12:1-17 Possible fix: add (Fractional a) to the context of the type signature for coefficient :: Num a => a In the expression: 1.0 In an equation for `coefficient': coefficient = 1.0 
+4
source share
1 answer

There is a function fromIntegral that converts an integer 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 a dotless style:

 result = (*) . fromIntegral 

Update Updated Question (@Drew)

Consider this code:

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

This is not true for him, as shown below. Since 1.0 is a literal for a fractional number (and not an integer), the GHC can only encode it as any type that can represent fractional numbers (forall a. Fractional a => a). However, you indicated that it must be valid for any number type (forall a. Num a => a). Some numeric types (e.g. Integer) cannot represent fractional values ​​and are not Fractional instances (rightly so), so this cannot be checked by typecheck. You can fix it as follows:

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

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

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

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

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

And then it should be checked. @singpolyma is right that your original mistake was partially related to monomorphism restriction, but you just had to make type signatures a bit more specific. If you want it to work with (Num a) => a, then the coefficient should be an integer (e.g. 1).

GHCi Update (@Marcin)

To use this in GHCi, I would suggest letting GHCi infer a type. If in this case you enter (in GHCi):

 let result val coefficient = fromIntegral val * coefficient 

Then GHCi will correctly infer the type of result. You can ask GHCi what type it thinks that something uses 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 to get an explicit type, but GHCi will make it monomorphic:

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

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

+13
source

Source: https://habr.com/ru/post/1445725/


All Articles