初学者到哈斯克尔

时间:2013-09-29 21:31:51

标签: haskell

   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 个答案:

答案 0 :(得分: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)

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

“裸体表情”错误意味着你在一条线上有一些不是功能的东西 - 你的最后一行。相反,我使用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:[]相同的[1,3,8],但不能执行1:3:8:()因为()是空元组,而不是空列表(类型错误),并且您无法执行[]:1:3:8,因为8不是列表,而:需要右侧的列表它。 (这意味着您可以快速添加到列表的前面,但不能快速添加到后面。)

也许值得你完成一个教程,回答所有练习 - 你似乎有一个关于Haskell编程的概念图,它缺乏实用细节。我可以推荐Learn You a Haskell for Great Good,这是一个快乐的,可访问的,你可以在线免费阅读。只记得实际做所有的练习,测试你的答案工作! (使用ghci或拥抱。)通过定期测试和检查,您将学得更快。

答案 1 :(得分:1)

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

首先,您得到的错误来自

 ():g++g1++g2

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

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

其次,该行不符合您的预期。 ()表示空元组,:是列表构造函数,++是列表追加。为了创建一个浮动元组^ 3

,这两者都没有意义

你需要一些东西:

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

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

如果要定义具有3个参数的函数,则该函数应如下所示:

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

请参阅? x y z是函数的输入变量。无论你放在=的左侧 是一个输入,无论来自右侧,都是输出。

好的,但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)))

并且一定要注意缩进,因为如果你把它放在与ver相同的位置,你就不会表达属于哪个函数。

答案 2 :(得分: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元组。

作为解决这个问题的潜在方法可能更好;您可以重新考虑您的函数来转换Location数组,并返回一个距离数组。这将允许您编写更优雅的解决方案

答案 3 :(得分: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

我希望这会有所帮助。