2012-02-20 39 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