Как создать оператор в Haskell?

Создание тройной логической таблицы, и я хотел бы создать свою собственную функцию для оператора, который я назову <=>.

Так, например, я хочу сделать это, но это неправильно. как правильно это сделать?

data Ternary = T | F | M
deriving (Eq,  Show, Ord)

<=> :: Ternary -> Ternary -> Ternary
<=> T F = F
<=> T T = T
<=> T M = M
<=> F F = T
<=> F T = F
<=> F M = M
<=> M F = M
<=> M T = M
<=> M M = T

person user1189352    schedule 20.02.2012    source источник
comment
Кстати, M <=> M должно быть M, а не T. Но это зависит от вашей семантики «Может быть».   -  person bitmask    schedule 20.02.2012
comment
Не забывайте, что вы можете установить арность и ассоциативность, используя infixl, infixr...   -  person Landei    schedule 20.02.2012


Ответы (4)


Просто добавьте круглые скобки вокруг вашего оператора:

(<=>) :: Ternary -> Ternary -> Ternary
(<=>) T F = F
(<=>) T T = T
(<=>) T M = M
(<=>) F F = T
(<=>) F T = F
(<=>) F M = M
(<=>) M F = M
(<=>) M T = M
(<=>) M M = T

Это превращает его из инфиксной формы в префиксную. В качестве альтернативы вы можете просто использовать инфикс в определении:

(<=>) :: Ternary -> Ternary -> Ternary
T <=> F = F
T <=> T = T
T <=> M = M
F <=> F = T
F <=> T = F
F <=> M = M
M <=> F = M
M <=> T = M
M <=> M = T
person Clark Gaebel    schedule 20.02.2012
comment
Есть ли способ создать что-то вроде оператора : cons? У оператора : cons есть такая особенность, когда он считает все, что находится справа, списком. Я пытался воссоздать оператор :, но он всегда требует круглых скобок справа. - person CMCDragonkai; 28.12.2014
comment
@ClarkGaebel: может быть, было бы интересно упомянуть и infix? - person Willem Van Onsem; 18.03.2015
comment
@CMCDragonkai Вы можете сделать то же самое самостоятельно следующим образом: data List a = Nil | a :- List a, а затем решающая часть: infixr 5 :-. Не обязательно должно быть 5, но это приоритет списков, просто должно быть infixr, а НЕ infixl или infix. infixl 9 по умолчанию - person semicolon; 15.04.2017

Имена функций с символами имеют другой синтаксис, чем без:

-- Works:
(<^>) :: Int -> Int -> Int
a <^> b = a + b

-- Doesn't work:
{-
<^> :: Int -> Int -> Int
<^> a b = a + b
-}

-- Works:
letters :: Int -> Int -> Int
letters a b = a + b

-- Doesn't work:
{-
(letters) :: Int -> Int -> Int
a letters b = a + b
-}

Я обещаю, хотя - Haskell стоит того, чтобы изучить сложные правила.

person amindfv    schedule 20.02.2012

Вы можете упростить (построчно) определение следующим образом:

(<=>) :: Ternary -> Ternary -> Ternary
T <=> T = T
F <=> F = T
M <=> M = T
M <=> _ = M
_ <=> M = M
_ <=> _ = F
person Thomas Eding    schedule 20.02.2012
comment
Мне это не кажется проще. - person Clark Gaebel; 22.02.2012
comment
Вот почему у меня там есть (line-wise). Хотя чистота спорная. Я могу лучше видеть код, потому что вынужден делать выводы о том, что он на самом деле делает, а не смотреть на необработанное табличное определение. Но это я. - person Thomas Eding; 22.02.2012
comment
ИМО, это проще, я могу быстро увидеть, что если они равны, то возвращают true, если они не равны, но один из них - возможно, то возвращают возможно, если они не равны и не включают возможно, то возвращают ложь. Единственная часть, которая может показаться мне удивительной, это то, что M <=> M является частью T. - person semicolon; 15.04.2017

Поскольку у вас есть Eq и Ord, вы можете сделать следующее:

data Ternary = T | F | M
deriving (Eq, Show, Ord)

(<=>) :: Ternary -> Ternary -> Ternary
x <=> y = if x == y then T else max x y

Если вам случится изменить его так, что M <=> M == M, то вы можете сделать следующее:

data Ternary = M | T | F
deriving (Eq, Show, Ord, Enum)

(<=>) :: Ternary -> Ternary -> Ternary
x <=> y = fromEnum $ rem (toEnum x * toEnum y) 3
person Olathe    schedule 24.02.2012