Haskell 类型错误`map (\idx -> (2.400 ** idx)/fact idx) [0..9]` `fact :: Int ->Int`,预期的整数,实际的双精度 [英] Haskell type error `map (\idx -> (2.400 ** idx) / fact idx) [0..9]` `fact :: Int -> Int`, Expected Int, Actual Double

查看:73
本文介绍了Haskell 类型错误`map (\idx -> (2.400 ** idx)/fact idx) [0..9]` `fact :: Int ->Int`,预期的整数,实际的双精度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在解决下面这个问题时,我遇到了一个奇怪的错误.

module Main where事实 :: Int ->整数事实 0 = 1事实 n = foldr (*) 1 [1..n]calc_e_to_power :: 双 ->双倍的calc_e_to_power x = foldr (+) 0 $ map (\idx -> (x ** idx)/fact idx) [0..9]主要:: IO()主要 = 做putStrLn $ 显示 $ calc_e_to_power 2.4000

我收到 fact 函数的类型错误,该函数表示预期的 Int,得到 Double.在这里idx的类型怎么可能是Double.

我知道 ** 会将除法的第一个表达式的类型转换为 Double,但是 2.3243/3 在 ghci 中工作得很好.当我删除 fact 的类型签名时,它符合并且完美运行.

不太确定我在这里遗漏了什么.

我还在 Repl 中重新创建了示例.有人能帮我理解这里有什么问题吗?

repl 上的代码链接 https://replit.com/@VipulSharma12/HeavyGrandioseCrypto#src/Main.hs

解决方案

在你的表达中:

map (\idx -> (x ** idx)/fact idx) [0..9]

fact 需要一个 Int 并返回一个 Int,所以 idx 应该是一个 Intfact idx 也是一个 Int.但这与 (**) 被定义为 (**) :: 浮动 a =>->->a 接受两个相同类型的元素,它们应该是 Floating 类型类的成员.

特别是因为 x 的类型是 Double,因此 x ** idx 将是 Double同样,这要求 idxDouble.但是idx 应该是fact idxInt,一个项目不能是Int>双倍同时.

我们可以做的是使用 (^) :: (Num a, Integral b) =>->b->a 接受 b 类型的项作为第二个操作数,这样 bIntegral 类型类,当 bInt 时就是这种情况.

现在分子 x ^ idx 的类型为 Double (因为 (^) 的类型为 (^) :: (Num a, Integral b) => a -> b -> afact idx 的类型为 Int.我们不能划分 >DoubleInt,因为 (/) :: 分数 a => a -> a -> a 需要两个操作数具有相同的类型,并且该类型应该是 Fractional 类型类的成员(并且 Int 不是该类型类的成员).

我们可以使用 fromIntegral:: (Integral a, Num b) =>->b 转换一个 Integral 数字(IntIntegral 类型类的成员),到任何类型 b 其中 bNum 类型类的成员(并且 Double 是此类型类的成员).

因此我们可以修复表达式并将其重写为:

calc_e_to_power :: Double ->双倍的calc_e_to_power x = foldr (+) 0 $ map (\idx -> (x ^ idx)/fromIntegral (fact idx)) [0..9]

我们可以使用 sum:: (Foldable f, Num a) =>f a ->a 避免使用 foldr 编写该部分:

calc_e_to_power :: Double ->双倍的calc_e_to_power x = sum (map (\idx -> (x ^ idx)/fromIntegral (fact idx)) [0..9])

While working on this problem below, I am getting a strange error.

module Main where

fact :: Int -> Int
fact 0 = 1
fact n = foldr (*) 1 [1..n]

calc_e_to_power :: Double -> Double
calc_e_to_power x = foldr (+) 0 $ map (\idx -> (x ** idx) / fact idx) [0..9]

main :: IO ()
main = do
  putStrLn $ show $ calc_e_to_power 2.4000

I am getting type error for fact function which says expected Int, got Double. How can the type of idx be Double here.

I am aware that ** will convert the type of first expression of division to Double, but 2.3243 / 3 works perfectly fine in ghci. When I remove the type signature of fact, it complies and works perfectly.

Not really sure what am I missing here.

I have also recreated the example in Repl. Can someone help me understand what's wrong here ?

Link to Code on repl https://replit.com/@VipulSharma12/HeavyGrandioseCrypto#src/Main.hs

解决方案

In your expression:

map (\idx -> (x ** idx) / fact idx) [0..9]

fact expects an Int and returns an Int, so idx should be an Int and fact idx is also an Int. But this clashes with the fact that (**) is defined as (**) :: Floating a => a -> a -> a takes two items of the same type that should be members of the Floating typeclass.

Especially since the type of x is Double, and thus x ** idx will be a Double as well, this requires idx to be a Double. But idx should be an Int for the fact idx, and an item can not be an Int and Double at the same time.

What we can do is work with (^) :: (Num a, Integral b) => a -> b -> a which accepts as second operand an item of type b such that b is a member of the Integral typeclass, which is the case when b is an Int.

Now the numerator x ^ idx will have type Double (since (^) has type (^) :: (Num a, Integral b) => a -> b -> a whereas fact idx has type Int. We can not divide a Double by an Int, since (/) :: Fractional a => a -> a -> a requires both operands to have the same type, and that type should be a member of the Fractional typeclass (and an Int is not a member of this typeclass).

We can work with fromIntegral :: (Integral a, Num b) => a -> b to convert an Integral number (Int is a member of the Integral typeclass), to any type b where b is a member of the Num typeclass (and Double is a member of this typeclass).

We thus can fix the expression and rewrite this to:

calc_e_to_power :: Double -> Double
calc_e_to_power x = foldr (+) 0 $ map (\idx -> (x ^ idx) / fromIntegral (fact idx)) [0..9]

We can work with sum :: (Foldable f, Num a) => f a -> a to avoid writing that part with foldr:

calc_e_to_power :: Double -> Double
calc_e_to_power x = sum (map (\idx -> (x ^ idx) / fromIntegral (fact idx)) [0..9])

这篇关于Haskell 类型错误`map (\idx -> (2.400 ** idx)/fact idx) [0..9]` `fact :: Int ->Int`,预期的整数,实际的双精度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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