首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Where子句中键入规范

在Where子句中键入规范
EN

Stack Overflow用户
提问于 2016-10-23 17:48:11
回答 2查看 385关注 0票数 3

作为家庭作业的一部分,我试着做一些非常简单的事情。我所需要做的就是编写一个函数,它包含一个由两个元组组成的数字列表,表示三角形的基长和高度长度,并返回与这些三角形对应的区域的列表。其中一个要求是,我通过定义函数并在where子句中声明其类型来做到这一点。到目前为止,我所做的一切都无法编译,以下是我所得到的:

代码语言:javascript
复制
calcTriangleAreas xs = [triArea x | x<-xs]
    where triArea:: (Num, Num) -> Num --this uses 4 preceding spaces 
triArea (base, height) = base*height/2

这在错误The type signature for ‘triArea’ lacks an accompanying binding中失败,在我看来,在WHER-子句中没有定义triArea。好的,让我们把它缩进以匹配where

代码语言:javascript
复制
calcTriangleAreas xs = [triArea x | x<-xs]
    where triArea:: (Num, Num) -> Num --this uses 4 preceding spaces 
    triArea (base, height) = base*height/2 --... and so does this

这一次无法编译信息特别少的错误消息parse error on input triArea。只是为了好玩,让我们试着把它缩进更多的地方,因为我们还可以做些什么:

代码语言:javascript
复制
calcTriangleAreas xs = [triArea x | x<-xs]
    where triArea:: (Num, Num) -> Num --this uses 4 preceding spaces 
        triArea (base, height) = base*height/2 --this has 8

但是,没有骰子,与相同的parse error消息失败。我试着用相等的、4空格的制表符来替换每个选项卡中的空格,但这没有帮助。前两个选项卡产生与空格相同的错误,但最后一个错误如下所示:

代码语言:javascript
复制
calcTriangleAreas xs = [triArea x | x<-xs]
    where triArea:: (Num, Num) -> Num --this uses a preceding tab character 
        triArea (base, height) = base*height/2 --this has 2

给出错误消息。

代码语言:javascript
复制
Illegal type signature: ‘(Num, Num) -> Num triArea (base, height)’
  Perhaps you intended to use ScopedTypeVariables
In a pattern type-signature

我不知道这是什么意思,但它似乎突然忽略了换行符。我一直在阅读“学习一个Haskell",我应该能够用前三章中提供的信息来完成这个任务,但是我已经仔细研究过了,而且它们从来没有指定在这些章节中定义在where子句中的函数的类型。为了记录在案,他们的例子似乎不尊重间隔,我照搬了其中一个例子的风格:

代码语言:javascript
复制
calcTriangleAreas xs = [triArea x | x<-xs]
    where triArea:: (Num, Num) -> Num --4 preceding spaces
          triArea (base, height) = base*height/2 --10 preceding spaces

但是,这也未能编译,说出了一个完全无法理解的错误信息:

代码语言:javascript
复制
Expecting one more argument to ‘Num’
    The first argument of a tuple should have kind ‘*’,
      but ‘Num’ has kind ‘* -> GHC.Prim.Constraint’
    In the type signature for ‘triArea’: triArea :: (Num, Num) -> Num
    In an equation for ‘calcTriangleAreas’:
        calcTriangleAreas xs
          = [triArea x | x <- xs]
          where
              triArea :: (Num, Num) -> Num
              triArea (base, height) = base * height / 2

当我google/hoogle的时候,我找不到任何东西,我看过this question,但它不仅显示haskell太高级,我读不懂,而且基于我不相信他们和我有同样的问题。我已经尝试指定calcTriangleAreas的类型,并且我尝试将triArea规范中的类型混成Floating,坦白地说,我已经到了极限。我的文件的最上面一行是module ChapterThree where,但除此之外,我在每个示例中显示的代码都是整个文件。

我正在编写32位Linux 18,我正在用ghc ChapterThree.hs Chapter3UnitTests.hs -o Test进行编译,ChapterThree.hs是我的文件,单元测试是由我的老师提供的,这样我就可以很容易地判断我的程序是否有效(它永远不会达到ChapterThreeUnitTests.hs的编译步骤,所以我不认为内容会很重要),我的ghc版本是7.10.3。

编辑:请注意,如果我完全删除类型规范,那么一切都会编译得很好,并且该函数通过了所有相关的单元测试。

求你了,把我从疯狂中拯救出来。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-10-23 17:52:16

上一个例子是正确的,但是您编写的类型没有意义。Num类约束,而不是类型。你可能想写:

代码语言:javascript
复制
calcTriangleAreas xs = [triArea x | x<-xs]
    where triArea:: Num a => (a, a) -> a
          triArea (base, height) = base*height/2 

规则是:作业必须对齐。

此外,(/)需要Fractional类:

代码语言:javascript
复制
calcTriangleAreas xs = [triArea x | x<-xs]
    where triArea:: Fractional a => (a, a) -> a
          triArea (base, height) = base*height/2 

注意,缩进级别是,而不是,与where的缩进级别有任何关系。例如,您可以这样编写代码:

代码语言:javascript
复制
calcTriangleAreas xs = [triArea x | x<-xs] where
    triArea:: Fractional a => (a, a) -> a
    triArea (base, height) = base*height/2 

缩进级别由where/let中的第一赋值或do块的第一行定义。所有其他行都必须与那一行对齐。

所以所有这些都是正确的:

代码语言:javascript
复制
f x = y where
  a = b
  y = ...

f x = y
  where a = b
        y = ...

f x = y
  where
    a = b
    y = ...
票数 6
EN

Stack Overflow用户

发布于 2016-10-24 09:16:37

吐露出完全无法理解的错误信息: 一个元组的第一个参数应该是“*”,但是“Num”有“* -> GHC.Prim.Constraint”类

为了补充巴库里的答案,让我为你破译一下。

错误是-一行一行:

  • Num还需要一个参数--我们应该从一些a中编写Num a
  • 元组类型(如(,) )期望类型作为参数。语句“应该有种类的*”意味着“应该是一种类型”。Haskell的kinding系统将*称为“类型”。我们有Int :: *String :: *(Maybe Char, [Int]) :: *。一元类型构造函数(如Maybe[] )不是类型,而是从类型到类型的函数。我们写Maybe :: *->*[] :: *->*。它们的类*->*使得有可能声明,由于Maybe :: *->*Char :: *,我们有类似于普通值级函数的Maybe Char :: * (“是一种类型”)。对类型构造函数具有类(,) :: *->*->*:它需要两种类型,并提供一种类型。
  • Num有善良的*-> Constraint。这意味着,对于每种类型的TNum T的类型都是Constraint,而不是(,)所期望的*。这引发了一种错误。类Constraint用于类型化约束,如Eq IntOrd BoolNum Int。这些不是类型,而是对类型的要求。当我们使用(+) :: Num a => a->a->a时,我们可以看到(+)适用于任何类型的a,只要该类型满足Num a,即是数字。由于Num T不是一种类型,所以我们不能编写Maybe (Num T)[Num T],我们只能编写例如Maybe a,并在上下文中要求a属于类型分类Num
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40206012

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档