简体   繁体   English

是什么导致Haskell这样的类型错误?

[英]What causes a type error like this in Haskell?

I'm playing with Haskell to evaluate simple limits with tables of values. 我正在与Haskell一起使用值表评估简单极限。 I have the following function defined: 我定义了以下函数:

f :: (Integral a) => a -> a
f x = div 1 $ subtract 6 x

and in GHCI, I let leftSide = [5.90, 5.91..5.99] and let rightSide = [6.10,6.09..6.01] , then: 在GHCI中,我let leftSide = [5.90, 5.91..5.99]let rightSide = [6.10,6.09..6.01] ,然后:

GHCI> map f leftSide

Which barfs up this error: 哪个阻止了此错误:

<interactive>:50:5
  No instance for (Integral Double) arising from a use of `f'
  Possible fix: add an instance declaration for (Integral Double)
  In the first argument of `map', namely `f'
  In the expression: map f leftSide
  In an equation for `it': it = map f leftSide

Changing my type declaration for f to (Integral Double a) => a -> a makes the compiler complain about how `Integral' is applied to too many type arguments. 将我的f的类型声明更改为(Integral Double a) => a -> a使编译器抱怨“ Integral”如何应用于太多类型参数。 What's going on here? 这里发生了什么?

I think you just tried the wrong division - you really want (/) not div ... 我认为您只是尝试了错误的除法 -您真的想要(/)而不是div ...

your problem is that div which demands an Integral type (for example an Integer ): 您的问题是需要Integral类型(例如Integer )的div

Prelude> :t div
div :: Integral a => a -> a -> a

but then you use it with a Fractional ( 6.10 , ...) by map ing it over your leftSide and rightSide 但是然后通过mapmap到您的leftSiderightSide ,将它与Fractional6.10 ,...) rightSide

now GHCi defaults this to Double - but Double is not an instance of Integral - this is exactly what Haskell is complaining about. 现在GHCI默认这Double -但Double是不是一个实例Integral -这正是Haskell是抱怨。


the thing you tried does not work and I guess you wanted to write (Integral a, Double a) => ... but in the end (if it would work - it does not since Double is type and not a type-class) it would be the same as saying f :: Double -> Double anyway - which would get you the error again (as there is no div for Double ) 您尝试过的东西不起作用,我想您想写(Integral a, Double a) => ...但是最后(如果可行的话-因为Double是type而不是type-class,所以没有用)就像说f :: Double -> Double -这将再次导致您错误(因为Double没有div

To make it short: use (/) instead of div and it should work: 简而言之: 使用(/)代替div ,它应该可以工作:

f :: Fractional r => r -> r
f x = (1 /) $ subtract 6 x

here is your first example: 这是您的第一个示例:

Prelude> let leftSide = [5.90, 5.91..5.99]
Prelude> map f leftSide
[-10.000000000000036,-11.111111111111128
,-12.49999999999999,-14.285714285714228
,-16.66666666666653,-19.999999999999716
,-24.999999999999424,-33.33333333333207
,-49.999999999996625,-99.99999999998437]

btw: you can make this shorter if you use point-free: 顺便说一句:如果您使用无点,则可以使它更短

f = (1 /) . (6 -)

or a bit cleaner / more readable if you write it out 还是写得更干净/可读性更好

f x = 1 / (6 - x)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM