Haskell乘以Int和实数 [英] Haskell multiply Int and real number

查看:140
本文介绍了Haskell乘以Int和实数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有

 系数:: ??????? 
系数= 1.0

  val :: Int 

我想做

 结果:: ??????? 
结果val系数= val *系数

我需要哪些类型的签名和转换函数做这个工作吗?如果我想能够将val推广到任何类型的Num,我必须做些什么?



这:

 系数= 1.0 

val :: Int
val = 3

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

给我这个编译器警告: p>

 无法从类型签名所绑定的上下文(数字a)
中推导出(a〜Double)
for result :: Num a => a
在Move.hs:17:1-41
`a'是一个刚性类型变量,由
绑定,result :: Num a => a在Move.hs:17:1
在'(*)'的第一个参数中,即'系数'
在表达式中:系数*(fromIntegral val)
在等式`结果':
结果=系数*(来自整数值)

我知道那不是什么我最初问,在清理我的代码时犯了一些错误。



现在使用系数类型:

 系数:: Num a => a 
系数= 1.0

val :: Int
val = 3

结果:: Num a =>一个
结果=系数*(来自整数val)

由此产生的错误:

 无法从上下文中的字面值'1.0'
导致(小数a)(数字a)
bound通过系数:: Num a =>的类型签名,在Move.hs:12:1-17
处的
可能的修正:
添加(小数a)到
的上下文中系数:: Num a => gt的类型签名; a
在表达式中:1.0
在系数公式中:系数= 1.0


解决方案

有一个函数fromIntegral,它将整数转换为任何其他数字类型。所以你可以这样做:

  result ::(Integral n,Num m)=> n  - > m  - > m 
结果val系数= fromIntegral val *系数

或者,无点式:

  result =(*)。 fromIntegral 



关于更新问题的更新(@Drew)



考虑这个代码:

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

这是无效的,如下所示。由于1.0是分数(不是整数)的文字,因此GHC只能将其编码为能够表示分数的任何类型(分数a => a)。但是,您已指定它对于任何数字类型都是有效的(例如,a。Num a => a)。某些数字类型(例如Integer)不能表示小数值,并且不是小数的实例(正确),所以这不能被检查。您可以如下解决这个问题:

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

这里GHC可以推断出类型,系数工作正常。值得注意的是,Fractional是Num的一个子类,因此所有属于Fractional的东西都必须是Num。如果我在我的答案的第一部分中看看函数,系数只需要是一个Num类型(因为我们只将它用于(*)),所以我们可以使用这个系数定义来代替该参数。您的问题出于完全相同的原因。

  result ::(Num a)=> a 
结果=系数* fromIntegral val

同样,这个函数的结果必须是与系数相同的类型。由于系数不能是任何Num类型,但只有一个小数类型,我们需要将其更改为:

  result ::(Fractional a)=> a 
结果=系数* fromIntegral val

然后,应该检查。 @singpolyma是正确的,你的原始错误部分与单态限制有关,但你只需要使类型签名稍微更具体。如果你想要它与(数字a)=> a一起工作,那么系数必须是一个整数(例如1)。

更新GHCi(@Marcin)



为了在GHCi中使用这个,我建议让GHCi推断类型。如果在这种情况下你输入(在GHCi):

  let result val系数= fromIntegral val *系数

code>

然后GHCi会正确推断结果的类型。您可以使用':t'命令询问GHCi它认为是什么类型:

  Prelude> :t结果
结果::(积分a1,数字a)=> a1 - > a - > a

如果您必须有明确的类型签名,您可以这样做:

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

尝试使用明确的类型,但GHCi会使这种单形:

  Prelude> :t结果
结果::整数 - >整数 - >整数

我们不想要(这是因为类型注释指的是lambda的值表达,而不是结果的声明)。我不知道如何让显式类型在这里工作,所以也许有人比我们更懂得回答:P


I have

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

and

val :: Int

and I would like to do

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

What type signatures and conversion functions do I need to do to make this work? What must I do on top of that if I want to have ability to generalize val to any kind of Num?

This:

coefficient = 1.0

val :: Int
val = 3

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

gives me this compiler warning:

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 thats not what I asked originally, I made some mistakes when sanitizing my code.

Now with a type for coefficient:

coefficient :: Num a => a
coefficient = 1.0

val :: Int
val = 3

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

the resulting 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

解决方案

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

这篇关于Haskell乘以Int和实数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆