关于函数isHullEdge,Haskell的类型错误

时间:2017-03-18 02:21:20

标签: haskell

我试图找出完成函数isHullEdge的最佳方法。我目前正在尝试使用列表理解,但我收到类型错误。我仍然是Haskell的初学者,因此我无法理解堆栈跟踪以找出需要修复的内容。

type Edge a = (Point a, Point a)

-- Given an edge (that determines a line), say whether, as one moves along the
-- edge from its first to its second point, one must turn right (1) or left (-1)
-- to get to the point, or whether the point is on the line itself (0).
lineSide :: Real a => Edge a -> Point a -> a
lineSide ((e1x,e1y),(e2x,e2y)) (px,py) = signum ((px-e1x)*(e2y-e1y) - (e2x-e1x)*(py-e1y))

-- isHullEdge returns true just in case all points are on the same side of or
-- on the line determined by an edge.
isHullEdge :: Real a => [Point a] -> Edge a -> Bool
isHullEdge points edge | length points == 0 = True
                       | length [x | x <- points, lineSide edge x >= 0 || lineSide edge x <= 0] == length points = True
                       | otherwise = False
mod11PA.hs:54:50: error:
* Couldn't match expected type `[t0]' with actual type `a'
  `a' is a rigid type variable bound by
    the type signature for:
      isHullEdge :: forall a. Real a => [Point a] -> Edge a -> Bool
    at mod11PA.hs:52:15
* In the expression: lineSide edge x
  In a stmt of a list comprehension: c <- lineSide edge x
  In the first argument of `(==)', namely
    `[c | x <- points, c <- lineSide edge x]'
* Relevant bindings include
    x :: Point a (bound at mod11PA.hs:54:32)
    edge :: Edge a (bound at mod11PA.hs:53:19)
    points :: [Point a] (bound at mod11PA.hs:53:12)
    isHullEdge :: [Point a] -> Edge a -> Bool
      (bound at mod11PA.hs:53:1)

1 个答案:

答案 0 :(得分:0)

您可能需要length [ c | x <- points, c <- lineSide edge x]而不仅仅是[ c | x <- points, c <- lineSide edge x]。等于0的列表没有任何意义。旁注,检查长度是否为零是不好的;它是一个O(n)计算。使用null检查列表是否空白,因为列表为O(1)。

使用all ((>=0) . lineSide edge) points作为您的条件是更惯用的解决方案。当你真的想要使用列表来做某事时,你应该只使用列表推导,而不是做这样的测试。请注意all f xs = foldl (\a x -> if f x then a else False) True xs