2012-02-20 45 views
21

Tạo bảng logic bậc ba và tôi muốn tạo chức năng riêng cho một toán tử mà tôi sẽ gọi <=>.Làm cách nào để tạo toán tử trong Haskell?

Vì vậy, ví dụ: tôi muốn thực hiện việc này, nhưng điều đó không đúng. cách chính xác để làm điều này là gì?

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

Cũng giống như một bên n ote, 'M <=> M' phải là' M' thay vì 'T'. Nhưng điều đó phụ thuộc vào ngữ nghĩa "Có thể" của bạn. – bitmask

+0

Đừng quên rằng bạn có thể thiết lập tính xác thực và kết hợp bằng cách sử dụng 'infixl',' infixr' ... – Landei

Trả lời

36

Chỉ cần thêm dấu ngoặc xung quanh nhà điều hành của bạn:

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

này biến nó từ dạng trung tố tiền tố hình thức. Ngoài ra, bạn chỉ có thể sử dụng ghi vào trong định nghĩa:

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

Có cách nào để tạo một cái gì đó giống như toán tử ':' cons? Toán tử ':' cons có tính năng đặc biệt này, nơi nó xem xét mọi thứ ở phía bên tay phải để trở thành một danh sách. Tôi đã cố gắng tạo lại toán tử ':', nhưng nó luôn yêu cầu dấu ngoặc đơn ở phía bên tay phải. – CMCDragonkai

+0

@ClarkGaebel: có lẽ nó có thể là thú vị để đề cập đến 'infix' là tốt? –

+0

@CMCDragonkai Bạn có thể tự làm điều tương tự theo cách sau: 'data List a = Nil | a: - Liệt kê a' và sau đó là phần quan trọng: 'infixr 5: -'. Không cần phải là 5, nhưng đó là ưu tiên của danh sách, chỉ cần là 'infixr' và NOT 'infixl' hoặc' infix'. 'infixl 9' là mặc định – semicolon

8

tên Chức năng với các biểu tượng có cú pháp khác nhau hơn những người không:

-- 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 
-} 

Tôi hứa, mặc dù - Haskell rất đáng học tập các quy tắc phức tạp.

+11

Để hoàn thành:' 'a' letters' b'' works… –

1

Bạn có thể đơn giản hóa (line-khôn ngoan) định nghĩa như sau:

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

Điều đó trông không đơn giản đối với tôi. –

+0

Đó là lý do tại sao tôi có một '(dòng-khôn ngoan)' trong đó. Rõ ràng là gây tranh cãi mặc dù. Tôi có thể nhìn thấy mã tốt hơn bởi vì tôi buộc phải suy ra những gì nó thực sự làm như trái ngược với nhìn vào một định nghĩa bảng thô. Nhưng đó là tôi. –

+0

IMO nó đơn giản hơn, tôi có thể nhanh chóng thấy rằng nếu chúng bằng nhau thì trả về true, nếu chúng không phải nhưng có thể là một, thì có thể trả về, nếu chúng không bằng nhau và không liên quan đến . Chỉ một phần mà tôi có thể thấy đáng ngạc nhiên là 'M <=> M' là phần' T'. – semicolon

0

Vì bạn có EqOrd, bạn có thể làm như sau:

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

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

Nếu bạn xảy ra để thay đổi nó để M <=> M == M, sau đó bạn có thể làm như sau:

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

(<=>) :: Ternary -> Ternary -> Ternary 
x <=> y = fromEnum $ rem (toEnum x * toEnum y) 3 
Các vấn đề liên quan