微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Haskell,在函数中乘以Int和Float

为什么在ghci我可以输入:
5.0 * (3 - 1)
> 10.0

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

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

我遇到错误? “不能匹配预期类型”浮点“与推断类型”Int“?
而如何编写一个需要一个浮点和2个整数参数的函数,并对它们执行上述操作?

我正在使用ghci v6.12.1,如果这有所作为…

解决方法

数字文字(即在Haskell代码中键入一个数字)不是一些固定类型.它们是多态的.他们需要在某种情况下进行评估,要求他们具有具体的类型.

所以5.0 *(3 – 1)的表达式不是将Int乘以浮点数. 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命令查看:

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

但是要实际评估那个表达式,我们需要这样做一些具体的类型.如果我们正在评估这一点,并将其传递给一些需要Float,Double或某些其他特定分数类型的函数,那么Haskell会选择一个.如果我们只是评估表达式而没有其他上下文要求它是一个特定的类型,Haskell有一些认的规则来自动为你选择一个(如果认规则不适用它将反而给你一个关于模糊类型变量的类型错误).

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

以上我评估了5.0 *(3 – 1),然后询问GHCi总是与其评估的最后一个值绑定的魔术变量的类型.这告诉我,GHCi已经认了我的Fractional a =>一个类型只是Double,为了计算表达式的值是10.0.在做这个评估时,它只会乘以(和减去)双打,它不会乘以一个双倍的Int.

现在,当您尝试多个数字文字,看起来可能是不同类型的时候,发生了什么.但是,您的测试函数不是将文字加倍,它是将特定已知类型的变量相乘.在Haskell中,由于*运算符的类型为Num a => a – > a – > a – 它需要两个相同数值类型的值,并为您提供该类型的结果.您可以将Int乘以Int获得Int,或者通过Float浮动获得浮点数.您不能将Int乘以浮点数获得一个???.

其他语言仅在某些情况下通过隐式插入转换函数支持这种操作. Haskell从不隐含地在类型之间转换,但它具有转换功能.如果您希望它们被调用,您只需要显式调用它们.这将做的诀窍:

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

原文地址:https://www.jb51.cc/css/217394.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。