作为家庭作业的一部分,我试着做一些非常简单的事情。我所需要做的就是编写一个函数,它包含一个由两个元组组成的数字列表,表示三角形的基长和高度长度,并返回与这些三角形对应的区域的列表。其中一个要求是,我通过定义函数并在where子句中声明其类型来做到这一点。到目前为止,我所做的一切都无法编译,以下是我所得到的:
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
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。只是为了好玩,让我们试着把它缩进更多的地方,因为我们还可以做些什么:
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空格的制表符来替换每个选项卡中的空格,但这没有帮助。前两个选项卡产生与空格相同的错误,但最后一个错误如下所示:
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给出错误消息。
Illegal type signature: ‘(Num, Num) -> Num triArea (base, height)’
Perhaps you intended to use ScopedTypeVariables
In a pattern type-signature我不知道这是什么意思,但它似乎突然忽略了换行符。我一直在阅读“学习一个Haskell",我应该能够用前三章中提供的信息来完成这个任务,但是我已经仔细研究过了,而且它们从来没有指定在这些章节中定义在where子句中的函数的类型。为了记录在案,他们的例子似乎不尊重间隔,我照搬了其中一个例子的风格:
calcTriangleAreas xs = [triArea x | x<-xs]
where triArea:: (Num, Num) -> Num --4 preceding spaces
triArea (base, height) = base*height/2 --10 preceding spaces但是,这也未能编译,说出了一个完全无法理解的错误信息:
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。
编辑:请注意,如果我完全删除类型规范,那么一切都会编译得很好,并且该函数通过了所有相关的单元测试。
求你了,把我从疯狂中拯救出来。
发布于 2016-10-23 17:52:16
上一个例子是正确的,但是您编写的类型没有意义。Num是类约束,而不是类型。你可能想写:
calcTriangleAreas xs = [triArea x | x<-xs]
where triArea:: Num a => (a, a) -> a
triArea (base, height) = base*height/2 规则是:作业必须对齐。
此外,(/)需要Fractional类:
calcTriangleAreas xs = [triArea x | x<-xs]
where triArea:: Fractional a => (a, a) -> a
triArea (base, height) = base*height/2 注意,缩进级别是,而不是,与where的缩进级别有任何关系。例如,您可以这样编写代码:
calcTriangleAreas xs = [triArea x | x<-xs] where
triArea:: Fractional a => (a, a) -> a
triArea (base, height) = base*height/2 缩进级别由where/let中的第一赋值或do块的第一行定义。所有其他行都必须与那一行对齐。
所以所有这些都是正确的:
f x = y where
a = b
y = ...
f x = y
where a = b
y = ...
f x = y
where
a = b
y = ...发布于 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。这意味着,对于每种类型的T,Num T的类型都是Constraint,而不是(,)所期望的*。这引发了一种错误。类Constraint用于类型化约束,如Eq Int、Ord Bool或Num Int。这些不是类型,而是对类型的要求。当我们使用(+) :: Num a => a->a->a时,我们可以看到(+)适用于任何类型的a,只要该类型满足Num a,即是数字。由于Num T不是一种类型,所以我们不能编写Maybe (Num T)或[Num T],我们只能编写例如Maybe a,并在上下文中要求a属于类型分类Num。https://stackoverflow.com/questions/40206012
复制相似问题