Haskell,在函数内乘以Int和float [英] Haskell, multiplying Int and Float within a function

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

问题描述

为什么在ghci中我可以输入:

  5.0 *(3  -  1)
> 10.0

但是,如果我尝试在.hs文件中创建一个函数并将其加载:

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

? 难以匹配预期类型'浮点数'与推断类型'Int'?
我该如何编写一个函数,它接受一个浮点数和2个整数参数,并对它们执行上述操作?



我使用的是ghci v6.12.1,如果这样做有区别...

解决方案

数字文字(即在Haskell代码中只输入一个数字)并不是固定类型,它们是多态的,需要在需要它们的具体类型中进行评估。



因此,表达式 5.0 *(3 - 1)不是乘以 Int by Float 5.0 必须是小数类型, 3 1 均为 Num 类型。 3 - 1 表示3和1必须是相同 Num 类型,但是我们仍然没有(更多)约束它是哪一个特定的结果

* 表示两个参数必须是相同的类型,结果也将是相同的类型。由于 5.0 是一些小数类型,所以(3-1)一定也是。我们已经知道 3 1 (3-1)必须是 Num 类型,但所有小数类型也是 Num 类型,所以这个需求是不冲突的。



最终结果是整个表达式 5.0 *(3-1 )是某种类型,它是小数 5.0 3 1 都是相同的类型。您可以在GHCi中使用:t 命令来查看:

 前奏> :t 5.0 *(3-1)
5.0 *(3-1)::小数a => a

但是为了实际评估该表达式,我们需要这样做一些具体类型。如果我们正在对此进行评估并将其传递给需要 Float Double 或某些其他特定<$ c的函数$ c> Fractional 类型,那么Haskell会挑选那个。如果我们只是在没有其他上下文的情况下评估表达式,Haskell会有一些默认规则为您自动选择一个(如果默认规则不适用,它会给您一个关于不明确类型变量的类型错误)。

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

以上我评估过 5.0 *(3 - 1),然后询问变量GHCi总是绑定到它所评估的最后一个值的魔术 it 变量的类型。这告诉我,GHCi默认了我的小数a =>为了计算表达式的值是 10.0 ,一个类型只是 Double >。在做这样的评估时,它只是多次(并减去) Double s,它从来没有乘以 Double code> Int






现在,当您尝试多个数字文字,看起来像它们可能是不同的类型。但是你的 test 函数不是乘以文字,而是乘以特定已知类型的变量。在Haskell中,不能将 Int 乘以 Float ,因为 * 运算符的类型为 Num a => a - > a - >一个 - 它采用相同数值类型的两个值,并为您提供该类型的结果。你可以用 Int 乘以一个 Int 得到一个 Int Float Float 得到 Float 。你不能用 Float 乘以 Int 得到 ??? < code。。

其他语言只有在某些情况下隐式地将调用插入转换函数才支持这种操作。 Haskell 从不在类型之间隐式转换,但它具有转换功能。如果你想让它们被调用,你只需要明确地调用它们。这将做到这一点:

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


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...

解决方案

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)

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

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