Ошибка с квадрантом, дающим функцию

Я попытался создать функцию, которая давала бы имя квадранта при вводе координат x и y. Однако я получаю сообщение об ошибке: «Ошибка синтаксического анализа при вводе ‘=’

Ошибка, модули загружены: нет».

Я попытался добавить "|иначе...", но это все равно не сработало. Я убедился, что рассмотрел все возможности x и y.

data Quadrants = Origin |
                 Quadrant_I | Quadrant_II | Quadrant_III | Quadrant_IV |
                 X_Axis_Positive | X_Axis_Negative | Y_Axis_Positive | Y_Axis_Negative
  deriving (Show, Eq)
quadrant :: Float -> Float -> Quadrants
quadrant x y
    |x>0 && y>0 = Quadrant_I
    |x<0 && y>0 = Quadrant_II
    |x<0 && y<0 = Quadrant_III
    |x>0 && y<0 = Quadrant_IV
    |x=0 && y=0 = Origin
    |x>0 && y=0 = X_Axis_Positive
    |x<0 && y=0 = X_Axis_Negative
    |x=0 && y>0 = Y_Axis_Positive
    |x=0 && y<0 = Y_Axis_Negative

person JJ chips    schedule 14.03.2016    source источник


Ответы (3)


x=0

= используется как ключевое слово для определений. Поскольку вы не можете (и не хотите) определить x как 0 на данный момент, вы получите ошибку синтаксического анализа. То, что вы ищете, это функция сравнения. В Haskell это ==, см. Data.Eq. .

person Daniel Jour    schedule 14.03.2016

Я думаю, вы можете упростить структуру, если отделите знак каждой координаты от другого типа и шаблона, совпадающего с промежуточным типом, т.е.

data Sign = Negative | Zero | Positive
sign x | x==0 = Zero
       | x>0  = Positive
       | otherwise = Negative

а потом

quadrant :: Float -> Float -> Quadrants
quadrant x y = go (sign x) (sign y)
       where go Zero Zero = Origin
                Zero Positive = Y_Axis_Positive
                ...

Или вы можете отказаться от типа Quadrants и вместо этого можете использовать кортеж (Sign, Sign), который может быть более полезен для следующих шагов.

person karakfa    schedule 14.03.2016
comment
Вы можете просто использовать compare 0 вместо sign и сопоставлять шаблоны с результирующими значениями Ordering. - person chepner; 14.03.2016

В основном это дубликат очень хорошего ответа karakfa, просто для того, чтобы указать, что Haskell поставляется с типом данных, изоморфным Sign, а именно Ordering.

quadrant :: Float -> Float -> Quadrants
quadrant x y = go (compare x 0) (compare 0 y)
               where go EQ EQ = Origin
                     go EQ GT = Y_Axis_Positive
                     go EQ LT = Y_Axis_Negative
            ...

Ваш тип Quadrants просто изоморфен парам значений Ordering, что означает, что вы можете написать такой код, как

type Quadrant = (Ordering, Ordering)
origin = (EQ, EQ)
quadrant_i = (GT, GT)
-- etc

quadrant :: Float -> Float -> Quadrant
quadrant x y = ((compare x 0), (compare y 0))

Недостаток этого заключается в том, что требуется, чтобы расширение языка соответствовало образцу, скажем, origin, а не (EQ, EQ) напрямую.

person chepner    schedule 14.03.2016