2012-02-20 57 views
21

製作一個三元邏輯表,我想爲一個我稱之爲<=>的操作員創建自己的函數。如何在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 
+3

就像一邊n 'M <=> M'應該是'M'而不是'T'。但這取決於你的「Maybe」語義。 – bitmask 2012-02-20 06:06:06

+0

不要忘記,你可以通過使用'infixl','infixr'來設置arity和associativity ... – Landei 2012-02-20 08:31:28

回答

36

只需添加括號在你的運營商:

(<=>) :: 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 
+0

有沒有一種方法可以創建類似':'cons運算符的東西? ':'cons運算符具有此特殊功能,它將右側的所有內容都視爲列表。我一直在嘗試重新創建':'運算符,但它總是需要右側的括號。 – CMCDragonkai 2014-12-28 03:10:14

+0

@ClarkGaebel:也許提到'infix'也許會很有趣? – 2015-03-18 19:01:11

+0

@CMCDragonkai你可以用下面的方法自己做同樣的事情:'data List a = Nil |答: - 列出一個',然後是關鍵部分:'infixr 5:-'。不一定是5,但這是列表的優先級,只需要「infixr」而不是「infixl」或「infix」。 'infixl 9'是默認的 – semicolon 2017-04-15 06:20:01

8

的符號功能名稱有不同的語法比沒有:

-- 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是非常值得學習複雜的規則。

+11

爲了完整性:''a'''b''作品... – 2012-02-20 11:11:30

1

可以簡化(線明智)的定義如下:

(<=>) :: Ternary -> Ternary -> Ternary 
T <=> T = T 
F <=> F = T 
M <=> M = T 
M <=> _ = M 
_ <=> M = M 
_ <=> _ = F 
+0

這對我來說並不簡單。 – 2012-02-22 05:05:54

+0

這就是爲什麼我在那裏有一個'(行)'的原因。清晰度雖然有爭議。我可以更好地看到代碼,因爲我不得不推斷它實際執行的操作,而不是查看原始製表定義。但那是我。 – 2012-02-22 08:18:03

+0

海事組織它更簡單,我可以很快看到,如果他們是平等的,然後返回true,如果他們不是,但一個是可能的,然後返回也許,如果他們不平等,不涉及可能然後返回false 。只有一部分我可能會感到驚訝的是'M <=> M'是'T'部分。 – semicolon 2017-04-15 06:23:26

0

既然你有EqOrd,你可以做到以下幾點:

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