简体   繁体   English

如何为该函数编写类型声明?

[英]How do I write a type declaration for this function?

I'm still rather new to Haskell and I've encountered a problem that probably shouldn't be too hard to solve but totally stumped me. 我对Haskell还是很陌生,我遇到了一个问题,可能不应该太难解决,但却让我很沮丧。

I've written a function: 我写了一个函数:

maxFor l n = n * m * (m + 1) / 2 where m = l `div` n

The function belongs to a small module which loads without problems, but throws two errors that are embarrassingly cryptic to me, whenever I try to use the function after loading the module: 该函数属于一个很小的模块,该模块加载时没有问题,但是每次在加载模块后尝试使用该函数时,都会抛出两个令我感到尴尬的错误:

<interactive>:182:1:
    No instance for (Integral a0) arising from a use of `maxFor'
    The type variable `a0' is ambiguous
    Possible fix: add a type signature that fixes these type variable(s)
    Note: there are several potential instances:
      instance Integral Int -- Defined in `GHC.Real'
      instance Integral Integer -- Defined in `GHC.Real'
      instance Integral GHC.Types.Word -- Defined in `GHC.Real'
    In the expression: maxFor 999 5
    In an equation for `it': it = maxFor 999 5

<interactive>:182:8:
    No instance for (Num a0) arising from the literal `999'
    The type variable `a0' is ambiguous
    Possible fix: add a type signature that fixes these type variable(s)
    Note: there are several potential instances:
      instance Num Double -- Defined in `GHC.Float'
      instance Num Float -- Defined in `GHC.Float'
      instance Integral a => Num (GHC.Real.Ratio a)
        -- Defined in `GHC.Real'
      ...plus three others
    In the first argument of `maxFor', namely `999'
    In the expression: maxFor 999 5
    In an equation for `it': it = maxFor 999 5

I understand it's telling me my function is missing a proper type declaration, but I don't understand how to write it without the compiler nagging again. 我知道这是在告诉我我的函数缺少正确的类型声明,但是我不理解如何在不再次编译器na的情况下编写它。 I've tried countless variants and that I don't understand the actual problem doesn't help me to solve the problem. 我尝试了无数种变体,但我不了解实际问题并不能帮助我解决问题。

Part of the problem might be that I'm using (/) and div in one function, so the needed type declaration will probably contain Fractional and/or Integral , since: 问题的一部分可能是我在一个函数中使用了(/)div ,因此所需的类型声明可能会包含Fractional和/或Integral ,因为:

(/) :: Fractional a => a -> a -> a

and: 和:

div :: Integral a => a -> a -> a

But that's as far as I've got and I'm stuck. 但这是我所能做到的,我被困住了。 How would I write the type declaration for maxFor ? 我将如何为maxFor编写类型声明? What am I doing wrong? 我究竟做错了什么? Am I missing or overlooking something that should be obvious? 我是否缺少或忽略了明显的东西?

Any help and constructive feedback is greatly appreciated. 任何帮助和建设性的反馈将不胜感激。

EDIT: I've found this answer on stack overflow, which already helps a little. 编辑:我已经在堆栈溢出上找到了这个答案,这已经有所帮助。 I'd still appreciate help, but I will of course delete the question, if it turns out I'm being an idiot and end up being downvoted. 我仍然很感谢您的帮助,但是,如果事实证明我是个白痴并且最终被人们低估了,我当然会删除这个问题。

Note: This post is written in literate Haskell . 注意:这篇文章是用识字的Haskell撰写的。 You can save it as Max.lhs and try it in your GHCi. 您可以将其另存为Max.lhs并在GHCi中尝试。


A quick solution 快速解决方案

First of all, lets reason your use of (/2) . 首先,让您使用(/2) Is the number n * m * (m + 1) odd or even? n * m * (m + 1)奇数还是偶数? Well, either m is odd, and m + 1 is even, and therefore the whole product is even, or m is even and the same arguments hold. 好吧,或者m为奇数, m + 1为偶数,因此整个乘积为偶数,或者m为偶数,并且相同的参数成立。

So instead of n * m * (m + 1) / 2 , we can use n * m * (m + 1) `div` 2 : 因此,我们可以使用n * m * (m + 1) `div` 2代替n * m * (m + 1) / 2 n * m * (m + 1) `div` 2

> maxFor l n = n * m * (m + 1) `div` 2 
>    where m = l `div` n

Now, all we have to to is to check the types of the functions we use: 现在,我们要做的就是检查我们使用的函数的类型:

(+)  :: Num a => a -> a -> a
(*)  :: Num a => a -> a -> a
div  :: Integral n => n -> n -> n

And that leads directly to your type: 这直接导致您输入:

> maxFor :: Integral n => n -> n -> n

Alternatively, you can use some specific type to get errors out: 另外,您可以使用某些特定类型来排除错误:

maxFor :: Integer -> Integer -> Integer
-- Now GHC yells at you since Integer doesn't have a Fractional instance
-- and you try to use (/).

Background information 背景资料

You've already recognized the problem. 您已经认识到问题所在。 div indicates that l and n are some integral types, but (/) indicates that they're fractional. div表示ln是某些整数类型,但(/)表示它们是分数。 In your usual Prelude , there is no data type that's an instance of both typeclasses. 在您通常的Prelude ,没有数据类型是两个类型类的实例。 You can check this in GHCi: 您可以在GHCi中进行检查:

Prelude> :info Fractional
class Num a => Fractional a where
  (/) :: a -> a -> a
  recip :: a -> a
  fromRational :: Rational -> a
    -- Defined in ‘GHC.Real’

instance Fractional Float -- Defined in ‘GHC.Float’
instance Fractional Double -- Defined in ‘GHC.Float’

Prelude> :info Integral
class (Real a, Enum a) => Integral a where
  quot :: a -> a -> a
  rem :: a -> a -> a
  div :: a -> a -> a
  mod :: a -> a -> a
  quotRem :: a -> a -> (a, a)
  divMod :: a -> a -> (a, a)
  toInteger :: a -> Integer
    -- Defined in ‘GHC.Real’
instance Integral Word -- Defined in ‘GHC.Real’
instance Integral Integer -- Defined in ‘GHC.Real’
instance Integral Int -- Defined in ‘GHC.Real’

This is the first part. 这是第一部分。

The second part stems from literals. 第二部分来自文字。 999 or 5 has type Num a => a . 9995类型为Num a => a Now GHC is between a rock and a hard place: it has to find a Num instance, that's both Integral and Fractional . 现在,GHC处于困境和困境之间:它必须找到一个Num实例,它既是Integral也是Fractional Since there's no such type (see above), GHC gives up due to ambiguity. 由于没有这样的类型(请参见上文),GHC由于模棱两可而放弃了。 You can check this too in GHCi: 您也可以在GHCi中进行检查:

Prelude> 5 :: Num a => a
5

Prelude> 5 :: (Fractional a, Integral a) => a
<interactive>:7:1:
    No instance for (Fractional a0) arising from a use of ‘it’
    The type variable ‘a0’ is ambiguous
    Note: there are several potential instances:
      instance Integral a => Fractional (GHC.Real.Ratio a)
        -- Defined in ‘GHC.Real’
      instance Fractional Double -- Defined in ‘GHC.Float’
      instance Fractional Float -- Defined in ‘GHC.Float’
    In the first argument of ‘print’, namely ‘it’
    In a stmt of an interactive GHCi command: print it

So this is mainly the reason why you end up with the error. 因此,这主要是导致出现错误的原因。

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

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