惯用列表构造
Idiomatic list construction
我对 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
函数将成为问题。我该如何考虑这个因素?还有其他可以改进的地方吗?
多次调用 addPoints 可以用折叠代替。正如评论中所建议的那样,反转您的 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]
这不会破坏封装(您可以用点列表以外的其他东西替换折线的实现)并按照它们将要结束的顺序使用新点(p3 在 p2 前面)等)
你的 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]
基本上,如果点的值在编译时是已知的,你可以只写这个列表,没有必要经历所有这些间接。
我对 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
函数将成为问题。我该如何考虑这个因素?还有其他可以改进的地方吗?
多次调用 addPoints 可以用折叠代替。正如评论中所建议的那样,反转您的 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]
这不会破坏封装(您可以用点列表以外的其他东西替换折线的实现)并按照它们将要结束的顺序使用新点(p3 在 p2 前面)等)
你的 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]
基本上,如果点的值在编译时是已知的,你可以只写这个列表,没有必要经历所有这些间接。