点列表的质心

问题描述 投票:0回答:2

Haskell的新手

问题是

-- The centroid of a list of points is a point whose x (and y) coordinates are
-- the means of the x (and y) coordinates of the points in the list.
--
-- You may assume the list contains at least one point.
--
-- > centroid [Pt 1 1, Pt 2 2]
-- Pt 1.5 1.5
-- > centroid [Pt (-1.5) 0, Pt 3 2, Pt 0 1]
-- Pt 0.5 1.0

尝试这样编码

data Point = Pt Double Double deriving (Show, Eq)

centroid :: [Point] -> Point

pointX :: Point -> Double
pointX (Pt x y) = x
pointY :: Point -> Double
pointY (Pt x y) = y

pointsX :: [Point] -> [Double]
pointsX xs = map pointX xs
pointsY :: [Point] -> [Double]
pointsY xs = map pointY xs

average :: [Double] -> Double
average xs = (sum xs) `div` (genericLength xs)

centroid cenpoint = (Pt average(pointsX cenpoint) average(pointsY cenpoint))

我得到

Project1.hs:35:22: error:
    • Couldn't match expected type ‘([Double] -> Double)
                                    -> [Double] -> Point’
                  with actual type ‘Point’
    • The function ‘Pt’ is applied to four arguments,
      but its type ‘Double -> Double -> Point’ has only two
      In the expression:
        (Pt average (pointsX cenpoint) average (pointsY cenpoint))
      In an equation for ‘centroid’:
          centroid cenpoint
            = (Pt average (pointsX cenpoint) average (pointsY cenpoint))
   |
35 | centroid cenpoint = (Pt average(pointsX cenpoint) average(pointsY cenpoint))
   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Project1.hs:35:25: error:
    • Couldn't match expected type ‘Double’
                  with actual type ‘[Double] -> Double’
    • Probable cause: ‘average’ is applied to too few arguments
      In the first argument of ‘Pt’, namely ‘average’
      In the expression:
        (Pt average (pointsX cenpoint) average (pointsY cenpoint))
      In an equation for ‘centroid’:
          centroid cenpoint
            = (Pt average (pointsX cenpoint) average (pointsY cenpoint))
   |
35 | centroid cenpoint = (Pt average(pointsX cenpoint) average(pointsY cenpoint))
   |                         ^^^^^^^

Project1.hs:35:33: error:
    • Couldn't match expected type ‘Double’ with actual type ‘[Double]’
    • In the second argument of ‘Pt’, namely ‘(pointsX cenpoint)’
      In the expression:
        (Pt average (pointsX cenpoint) average (pointsY cenpoint))
      In an equation for ‘centroid’:
          centroid cenpoint
            = (Pt average (pointsX cenpoint) average (pointsY cenpoint))
   |
35 | centroid cenpoint = (Pt average(pointsX cenpoint) average(pointsY cenpoint))
   |
haskell
2个回答
1
投票

您做得很好-请注意编译错误如何全部指向您的最后一行(centroid的定义)。它们都是由于不正确的包围而造成的。这应该是这样:

centroid cenpoint = Pt (average (pointsX cenpoint)) (average (pointsY cenpoint))

即,所得Pt值的x坐标是相应点的x坐标的平均值(pointsX cenpoint是x坐标的列表,因此average (pointsX cenpoint)是它们的平均值) ,对于y坐标也是如此。

与您的不正确版本相比(在不更改编译器解释方式的情况下,我进行了一些整理):

Pt average (pointsX cenpoint) average (pointsY cenpoint)

这意味着您将Pt函数应用于4个参数:averagepointsX cenpointaveragepointsY cenpoint。这根本不起作用,因为Pt函数仅接受2个参数。


1
投票

这里的主要问题是您像使用Java,C ++或Python这样的语言来调用函数。

您需要将average包装在括号中,例如:

centroid cenpoint = Pt (average (pointsX cenpoint)) (average (pointsY cenpoint))

作为@dfeuer says,此处不需要外部括号。

此外,由于您正在使用(/),而div适用于Double类型,因此您可能想在div上使用Integral

average :: [Double] -> Double
average xs = sum xs / genericLength xs
© www.soinside.com 2019 - 2024. All rights reserved.