data Point = Point Float Float deriving (Show)
data Line = Line Point Point deriving (Show)
onLine :: Line -> Point -> Bool
onLine (Line (Point x1 y1) (Point x2 y2)) (Point x y) = True
有没有办法不使用这么多括号?
答案 0 :(得分:5)
我建议使用名为hlint的工具来识别可以简化代码的地方。
在您的代码中/以书面形式/,您没有使用值x1
,y1
,x2
,y2
,x
或{{ 1}},所以你可以写:
y
但是,我认为这只是一个存根,实际上你会对变量做些什么。通常,如果您确实需要引用所有这些变量,那么您需要按照自己的方式编写它。但是,也许您正在使用只需要整个行值的辅助函数。然后你可以这样写:
onLine _ _ = True
或者,您可以使用访问器函数从点和线中提取x和y坐标,但在这种情况下,它可能会使您的代码变得更加混乱。
此外,在Haskell中,我认为使用onLine l p = blah blah blah
-- use slope l and yIntercept l to figure out if p is on the line
slope :: Line -> Float
slope (Line (Point x1 y1) (Point x2 y2)) = (y2 - y1) / (x2 - x1)
yIntercept :: Line -> Float
yIntercept (Line (Point x1 y1) (Point x2 y2)) = blah blah blah
而不是Double
通常更有效。
答案 1 :(得分:3)
有时您可以使用记录符号避免使用括号,有时使用$
,有时使用中缀函数,有时候如果不过量则可以使用。
让我们使用记录表示法来获取坐标的重要访问权限,但我们将单独留下Line
。
data Point = Point {x::Double,y::Double} deriving (Show)
data Line = Line Point Point deriving (Show)
这定义了x :: Point -> Double
和y :: Point -> Double
。
没有浮点数相等的东西,但我会大致正确:
accuracy = 0.000000000001
is :: Double -> Double -> Bool
is x y = abs (x - y) < accuracy
我可以用x point1 `is` x point2
整齐地避免括号is (x point1) (x point2)
当您的数据结构没有与模式匹配嵌套时,可以轻松阅读几个括号:
gradient :: Line -> Double
gradient (Line one two) = (y two - y one) / (x two - x one)
但由于功能x
和y
,我们可以在不使用过多括号的情况下更深入一级。
asFunction :: Line -> (Double -> Double) -- ( ) for clarity, not necessity
asFunction l@(Line point _) = \xx -> gradient l * (xx - x point) + y point
注意我已使用l@
为(Line point _)
引入别名以保存右侧的输入。
现在我们可以使用中缀函数技巧来删除一些括号:
onLine :: Line -> Point -> Bool
onLine l p = l `asFunction` x p `is` y p
在右侧,您可以使用$
删除括号,但不能在模式匹配的左侧使用它,因为它是一个函数f $ x = f x
。例如
this (that (the other thing (something other)))
= this $ that $ the other thing $ something other
= this . that . the other thing $ something other
答案 2 :(得分:1)
你可以通过定义访问器来获取行并在函数内分开,但是如果没有括号,就无法进行模式匹配。
答案 3 :(得分:1)
摆脱括号的另一种方法是在多个case表达式中进行模式匹配:
onLine l p = case l of
Line p1 p2 -> case p1 of
Point x1 y1 -> case p2 of
Point x2 y2 -> case p of
Point x y -> True -- you can use x1,y1,x2,y2,x and y here
这与编译器“转换”模式匹配的内容很接近,但当然这并没有太大的改进!
但是,有很多方法可以编写这个表达式,也转换为相同的级联模式匹配;这是一个:
onLine l p = let
Line (Point x1 y1) (Point x2 y2) = l
Point x y = p
in True
这是另一个:
onLine l p = True where
Line (Point x1 y1) (Point x2 y2) = l
Point x y = p
在我看来,最后一个非常好看且可读,但其他建议要好得多,因为它们会带来更好的结构化程序!
(有一些关于无法反驳的模式的东西,我正在掩饰,这只适用于单构造函数数据类型)