惯用列表构建

时间:2015-06-17 13:39:21

标签: list haskell functional-programming idiomatic

我对Haskell和一般的函数式编程都很陌生,所以我真的不知道如何使这段代码成为惯用语:

type Coord = Double
data Point = Point Coord Coord Coord deriving Show

type Polyline = [Point]

-- Add a point to a polyline
addPoint :: Polyline -> Point -> Polyline
addPoint line p = p:line

line :: Polyline
line = []

constructLine :: Polyline -> Polyline
constructLine line =
    let 
        p1 = Point 2 4 87
        p2 = Point 3 7 2
        p3 = Point 23 4 8
    in addPoint (addPoint (addPoint line p1) p2) p3

main :: IO() 
main = do
    putStrLn ( show (constructLine line))

我的问题出在constructLine函数中。如果我想添加很多点,嵌套的addPoint函数将成为一个问题。我怎么能这个因素呢?您是否看到其他可以改进的事情?

2 个答案:

答案 0 :(得分:5)

对addPoints的多次调用可以用fold替换。正如评论中所建议的那样,反转你的addPoint函数会让事情变得更容易:

addPoint' :: Point -> Polyline ->  Polyline
addPoint' p line = p:line

那么你的constructLine函数可以构建一个临时的点列表来添加使用折叠:

constructLine :: Polyline -> Polyline
constructLine line =
    let
        p1 = Point 2 4 87
        p2 = Point 3 7 2
        p3 = Point 23 4 8
    in foldr addPoint' line [p3,p2,p1]

这不会打破封装(你可以用Point列表替换你的Polyline实现)并按照他们最终的顺序使用新点(p2在p2前面等等。)

答案 1 :(得分:2)

您的constructLine示例只是让我觉得这是一个冗长的版本:

constructLine :: Polyline -> Polyline
constructLine line = [Point 23 4 8, Point 3 7 2, Point 2 4 87] ++ line

我不知道你是否已经碰到过这些,但只是为了确定:

  • [Point 23 4 8, Point 3 7 2, Point 2 4 87]只是一个列表文字。
  • ++是附加列表的功能。

通常,要将多个元素添加到列表中,您要执行的操作是列出要添加的元素,并将该列表与原始列表一起附加。

这种模式仍在继续。如果我们注意到line[]定义的常量,那么整个程序实际上只是一个冗长的版本:

type Coord = Double
data Point = Point Coord Coord Coord deriving Show

main :: IO () 
main = putStrLn (show points)
     where points = [Point 23 4 8, Point 3 7 2, Point 2 4 87]

基本上,如果分数'值在编译时已知,您可以列表,不需要经历所有这些间接。