2013-07-03 2 views
1
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 

Есть ли способ не использовать столько скобок?Скобки в этом коде Haskell

+0

Вы можете удалить скобки вокруг 'show' вытекающих п. Больше вы ничего не можете сделать; в конце концов, как вы отделяете шаблоны аргументов друг от друга без брекетов? –

ответ

5

Я рекомендую инструмент под названием hlint для определения мест, где вы можете упростить код.

В коде/как написано /, вы не используете значения x1, y1, x2, y2, x или y, так что вы могли бы просто написать:

onLine _ _ = True 

Однако, я полагаю, что это просто заглушки, и на самом деле вы будете что-то делать с переменными. В общем, если вам действительно нужно ссылаться на все эти переменные, тогда вам нужно написать его так, как вы это сделали. Однако, возможно, вы используете вспомогательную функцию, для которой требуется только значение всей строки. Тогда вы могли бы написать что-то вроде:

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 

В качестве альтернативы, вы можете просто использовать аксессор функции для извлечения х и у координаты из точек и линий, но в данном случае это, вероятно, сделать код грязнее.

Кроме того, в Haskell я считаю, что в целом более эффективно использовать Double, а не Float.

+0

Спасибо за последний намек! Я также обнаружил, что, используя float, я не могу использовать отрицательные числа, такие как -1. Какие-либо предложения ? – osager

+4

Вы можете использовать отрицательные числа, это просто, что иногда вам нужно заключить их в круглые скобки. См. Раздел «Арифметическая причуда: запись отрицательных чисел» в главе 1 «Real World Haskell» (http://book.realworldhaskell.org/read/getting-started.html) – mhwombat

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) 

Но мы можем пойти на один уровень глубже остроумие hout с использованием чрезмерных скобок из-за функций x и y.

asFunction :: Line -> (Double -> Double) -- () for clarity, not necessity 
asFunction [email protected](Line point _) = \xx -> gradient l * (xx - x point) + y point 

Примечание Я использовал [email protected] ввести псевдоним для (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 
+0

Спасибо @leftaroundabout. Это действительно то, что я намеревался. – AndrewC

1

Другой способ избавления от скобок, чтобы сделать сравнение с образцом в ряде случаев выражения:

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 

Это близко к тому, что «переводит» компилятор в patternmatches к , но, конечно же, это не очень хорошее улучшение!

Однако существует несколько способов написания этого выражения, что также перевести на тот же каскадный шаблон; вот один:

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 

Последний один очень приятно и читаемым, на мой взгляд, но другие предложения гораздо лучше, так как они ведут к лучшему структурированная программа!

(Там какие-то вещи о неопровержимых моделях, которые я замазывание, и это работает только для одного конструктора типов данных)

Смежные вопросы