2012-02-20 11 views
21

Creazione di una tabella logica ternaria e vorrei creare la mia funzione per un operatore che chiamerò <=>.Come posso creare un operatore in Haskell?

Quindi, per esempio, voglio farlo, ma non è giusto. qual è il modo corretto per farlo?

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

Proprio come un lato n Nota: 'M <=> M' dovrebbe essere' M' piuttosto che 'T'. Ma questo dipende dalla tua semantica "Forse". – bitmask

+0

Non dimenticare che puoi impostare arity e associatività usando 'infixl',' infixr' ... – Landei

risposta

36

Basta aggiungere parentesi attorno al proprio operatore:

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

Questo trasforma dalla forma infissa al prefisso modulo. In alternativa, si può semplicemente utilizzare infisso nella definizione:

(<=>) :: 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'è un modo per creare qualcosa come l'operatore ':' cons? L'operatore ':' cons ha questa caratteristica speciale in cui considera tutto sul lato destro una lista. Ho cercato di ricreare l'operatore ':', ma richiede sempre parentesi sul lato destro. – CMCDragonkai

+0

@ClarkGaebel: forse potrebbe essere interessante menzionare anche 'infix'? –

+0

@CMCDragonkai Puoi fare la stessa cosa tu stesso nel seguente modo: 'data list a = Nil | a: - Elenca a' e quindi la parte cruciale: 'infixr 5: -'. Non deve essere 5, ma questa è la precedenza delle liste, deve essere solo 'infixr' e NOT' infixl' o 'infix'. 'infixl 9' è il default – semicolon

8

I nomi delle funzioni con simboli hanno sintassi diversa rispetto a quelli senza:

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

lo prometto, anche se - Haskell vale la pena di imparare le regole complesse.

+11

Per completezza:' 'a' letters' b'' funziona ... –

1

È possibile semplificare la definizione (line-saggio) come segue:

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

Questo non mi sembra più semplice. –

+0

Ecco perché ho un '(line-wise)'. La chiarezza è discutibile però. Riesco a vedere meglio il codice perché sono costretto a dedurre ciò che effettivamente fa piuttosto che guardare una definizione tabulata non elaborata. Ma sono io. –

+0

IMO è più semplice, posso vedere rapidamente che se sono uguali restituiscono true, se non lo sono ma uno è un forse, quindi restituiscono forse, se non sono uguali e non implicano un forse quindi restituiscono false . Solo una parte che potrei trovare sorprendente è la 'M <=> M' che è la parte' T'. – semicolon

0

Dal momento che hai Eq e Ord, è possibile effettuare le seguenti operazioni:

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

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

Se vi capita di cambiamento in modo che M <=> M == M, quindi è possibile effettuare le seguenti operazioni:

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

(<=>) :: Ternary -> Ternary -> Ternary 
x <=> y = fromEnum $ rem (toEnum x * toEnum y) 3 
Problemi correlati