0
   ver :: (Float,Float)->(Float,Float)->(Float,Float)->(Float,Float,Float)
   ver g=sqrt((((fst x -fst y)^2)+((snd x -snd y)^2))) 
   ver g1=sqrt((((fst x -fst z)^2)+((snd x -snd z)^2))) 
   ver g2=sqrt((((fst y -fst z)^2)+((snd y -snd z)^2)))
   ():g++g1++g2

我写了这个,但我不断收到错误:顶层的裸表达式

我想要做的是取 3 个建筑物之间的距离并将它们作为一个元组呈现,例如:(dAB,dBC,dAC)

4

4 回答 4

3

你的意思是

ver :: (Float,Float)->(Float,Float)->(Float,Float)->(Float,Float,Float)
ver x y z = (g,g1,g2) where
   g=sqrt((((fst x -fst y)^2)+((snd x -snd y)^2))) 
   g1=sqrt((((fst x -fst z)^2)+((snd x -snd z)^2))) 
   g2=sqrt((((fst y -fst z)^2)+((snd y -snd z)^2)))

编译并给出

> ver (1,1) (4,-3) (8,0)
(5.0,7.071068,5.0)

...作为参数给出的三对点之间的距离的三元组(三元组)。

“裸表达式”错误意味着您在不是函数的行上有一些东西 - 您的最后一行。相反,我曾经where介绍过您的中间计算,但我也可以使用let ... in ...

ver' :: (Float,Float)->(Float,Float)->(Float,Float)->(Float,Float,Float)
ver' x y z = let
   g=sqrt((((fst x -fst y)^2)+((snd x -snd y)^2))) 
   g1=sqrt((((fst x -fst z)^2)+((snd x -snd z)^2))) 
   g2=sqrt((((fst y -fst z)^2)+((snd y -snd z)^2)))
     in (g,g1,g2)

这个符号():g++g1++g2看起来你在元组和列表之间有点混淆了。您可以从空列表构建列表,但不能构建元组。

例如,你可以做1:3:8:[]which和_列表在它的右边。(这意味着您可以快速添加到列表的前面,但不能很快添加到后面。)[1,3,8]1:3:8:()()[]:1:3:88:

也许值得你学习一个教程,回答所有的练习——你似乎对 Haskell 编程有一个概念性的画面,但缺乏实际的细节。我可以推荐Learn You a Haskell for Great Good,它写得很愉快,易于访问,您可以在线免费阅读。只要记住实际做所有的练习,并测试你的答案是否有效!(使用 ghci 或拥抱。)通过定期测试和检查,您会学得更快。

于 2013-09-29T22:26:54.347 回答
1

在我开始列出您的代码有什么问题以及如何修复它之前,我建议您先阅读一些教程或 haskell 介绍性文本,例如Learn You a Haskell for Great Good,因为您的代码表明您没有掌握一些基本语法。

首先,你得到的错误来自

 ():g++g1++g2

在haskell中,top level(0缩进)中的任何内容都必须是某种声明(导入,类型签名)或函数实现方式的一部分。

所以你有一个实现(虽然错了,但稍后会更多),但问自己,“我怎么知道这条线与 ver 相关?” 好吧,在 haskell 中,您有特殊的关键字,例如letorwhere来表达这一点。由于您没有这些,因此该代码行丢失了,与实现无关,并且它不能存在于顶层 - 从而导致错误。我将展示如何尽快解决这个问题。

其次,这条线没有达到你的预期。()表示一个空元组,:是一个列表构造函数并且++是列表追加。为了创建一个浮动元组,这两个都没有意义^ 3

你需要一些东西:

(,,) g g1 g2 
--or
(g,g1,g2)

第三,您的函数实现与类型指定的内容无关。也就是说,您有 3 个版本来ver代替ver带有 3 个参数的版本。再问问自己“我怎么知道 xyz 来自哪里”?

如果你想定义一个有 3 个参数的函数,函数应该是这样的:

ver x y z = -- Insert the calculations you want.

看?xyz 是函数的输入变量。你放在左边的= 东西是输入,右边的东西是输出。

好的,但是 g g1 g2 怎么样?我怎么知道我想计算这 3 个值,给它们命名,然后使用它们?

是时候使用where我之前告诉过你的那个条款了。看看你的函数应该是什么样子:

ver :: (Float,Float)->(Float,Float)->(Float,Float)->(Float,Float,Float)
ver x y z = (g,g1,g2)
     where g=sqrt((((fst x -fst y)^2)+((snd x -snd y)^2))) 
           g1=sqrt((((fst x -fst z)^2)+((snd x -snd z)^2))) 
           g2=sqrt((((fst y -fst z)^2)+((snd y -snd z)^2)))

并且一定要注意缩进,因为如果你把 where 放在与 ver 相同的级别,你并没有表达 where 属于哪个函数。

于 2013-09-29T22:37:00.773 回答
0

我相信您希望分别对所有三个元组进行模式匹配,例如

type Location = (Float, Float)
ver :: Location -> Location -> Location -> (Float, Float, Float)
ver (aX, aY) (bX, bY) (cX, cY) = (0, 0, 0) {- Your logic -}

这将使您可以访问所有三个位置,即 IE x,y 元组。

作为处理此问题的更好方法;您可以重新考虑您的函数来转换位置数组,并返回例如距离数组。这将允许您编写更优雅的解决方案

于 2013-09-29T22:26:01.570 回答
0

问题出在最后一行:():g++g1++g2. 那是赤裸裸的表达。在文件的顶层,你只能有像这样的定义ver g=sqrt((((fst x -fst y)^2)+((snd x -snd y)^2)))或像ver :: (Float,Float)->(Float,Float)->(Float,Float)->(Float,Float,Float). 要摆脱解析错误,只需从文件中删除最后一行。

但是,在您摆脱解析错误之后,您将收到另一个关于与ver您在注释中所说的不匹配的类型的错误。这是一个很好的论据,可以像您所做的那样进行显式类型注释,因为它可以清楚地说明是否对代码的作用存在误解。在您的情况下,您似乎认为该ver函数一次只接受一行的争论,这是不正确的。就目前而言,类型ver应该是t -> Double. 您可以通过注释掉类型注释、在 ghci 中加载函数并键入来检查这一点:t ver。这将为您提供 Haskell 看到的类型。

我认为您前进的最简单方法是,如果我给您一个工作示例:

cityA = (3,4)
cityB = (1,2)
cityC = (6,3)

dist :: (Double, Double) -> (Double, Double) -> Double
dist city1 city2 = sqrt((fst city1 - fst city2)^2 + (snd city1 - snd city2)^2)

tripleDist :: (Double, Double) -> (Double, Double) -> (Double, Double) -> (Double, Double, Double)
tripleDist city1 city2 city3 = (d12, d13, d23)
    where d12 = dist city1 city2
          d13 = dist city1 city3
          d23 = dist city2 city3

dists = tripleDist cityA cityB cityC

我希望这有帮助。

于 2013-09-29T22:26:20.083 回答