作为家庭作业的一部分,我试图做一些非常简单的事情。我需要做的就是编写一个函数,该函数接收表示三角形的基本长度和高度长度的2元组数字列表,并返回与这些三角形对应的区域列表。其中一个要求是我通过定义一个函数并在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
,这对我来说听起来像triArea没有在where子句中定义。好的,让我们缩进它以匹配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
。只是为了好玩,让我们再尝试缩进它,因为idk还有什么可做的:
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
我不知道那是什么意思,但似乎突然忽略了新行。我一直在阅读&#34;了解你一个Haskell&#34;,我本来应该能够用前三章中提供的信息做到这一点,但我已经进行了搜索那些并且它们从未指定那些章节中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 Mint 18,我正在使用ghc ChapterThree.hs Chapter3UnitTests.hs -o Test
进行编译,其中ChapterThree.hs是我的文件,单元测试由我的老师给出,所以我可以很容易判断我的程序是否有效(它从未进入ChapterThreeUnitTests.hs的编译步骤,所以我认为内容不重要),而我的ghc版本是7.10.3。
编辑:请注意,如果我只是完全删除类型规范,那么一切都编译得很好,并且该函数会传递所有相关的单元测试。
拜托,救我脱离疯狂。
答案 0 :(得分:6)
你的最后一个例子是正确的,但你写的类型没有意义。 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 = ...
答案 1 :(得分:0)
吐出完全不可理解的错误信息:
Expecting one more argument to ‘Num’ The first argument of a tuple should have kind ‘*’, but ‘Num’ has kind ‘* -> GHC.Prim.Constraint’
为了补充Bakuriu的答案,让我为你解读。
错误说 - 逐行:
Num
期待再有一个论点 - 我们应该从某些Num a
a
(,)
之类的元组类型需要一个类型作为参数。声明&#34;应该有*
&#34;意味着&#34;应该是一种类型&#34;。 Haskell的绑定系统将*
关联为&#34;类型&#34;。我们有例如Int :: *
,String :: *
和(Maybe Char, [Int]) :: *
。诸如Maybe
和[]
之类的一元类型构造函数不是类型,而是从类型到类型的函数。我们写Maybe :: *->*
和[] :: *->*
。他们的*->*
种类可以说明,自Maybe :: *->*
和Char :: *
以来,我们Maybe Char :: *
(&#34;类型为&#34;)与普通价值相似级别的功能。对类型构造函数具有类(,) :: *->*->*
:它需要两种类型并提供类型。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
。