2012-02-20 16 views
21

Haciendo una tabla de lógica ternaria, y me gustaría hacer mi propia función para un operador que llamaré al <=>.¿Cómo creo un operador en Haskell?

Entonces, por ejemplo, quiero hacer esto, pero eso no es correcto. ¿Cuál es la forma correcta de hacer esto?

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

Just a a side n ote, 'M <=> M' debe ser' M' en lugar de 'T'. Pero eso depende de tu semántica "Quizás". – bitmask

+0

No olvide que puede establecer arity y asociatividad usando 'infixl',' infixr' ... – Landei

Respuesta

36

Sólo tiene que añadir paréntesis alrededor de su operador:

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

Esto lo convierte de forma infija para prefijar formulario. Como alternativa, puede simplemente usar infija en la definició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 
+0

¿Hay alguna manera de crear algo así como el operador ':' cons? El operador ':' contra tiene esta característica especial en la que considera que todo lo que está a la derecha es una lista. He intentado recrear el operador ':', pero siempre requiere paréntesis en el lado derecho. – CMCDragonkai

+0

@ClarkGaebel: tal vez podría ser interesante mencionar 'infix' también? –

+0

@CMCDragonkai Puede hacer lo mismo usted mismo de la siguiente manera: 'data List a = Nil | a: - Lista un 'y luego la parte crucial:' infixr 5: -'. No tiene que ser 5, pero esa es la prioridad de las listas, solo tiene que ser 'infixr' y NO' infixl' o 'infix'. 'infixl 9' es el valor predeterminado – semicolon

8

nombres de función con símbolos tienen una sintaxis diferente que los que no tienen:

-- 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 prometo, aunque - Haskell es bien vale la pena aprender las reglas complejas.

+11

Para completar:' 'a' letters' b'' funciona ... –

1

Se puede simplificar (línea en cuanto a) la definición de la siguiente manera:

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

Eso no me parece más sencillo. –

+0

Es por eso que tengo un '(en línea)' ahí. La claridad es discutible sin embargo. Puedo ver el código mejor porque me veo obligado a deducir lo que realmente hace en lugar de mirar una definición tabulada sin formato. Pero ese soy yo. –

+0

IMO es más simple, puedo ver rápidamente que si son iguales, entonces devuelve verdadero, si no lo son, pero uno es tal vez, entonces regresa tal vez, si no son iguales y no implican un tal vez, entonces devuelve falso . La única parte que podría sorprenderme es la 'M <=> M' que es' T'. – semicolon

0

Puesto que usted tiene Eq y Ord, puede hacer lo siguiente:

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

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

Si lo hace pasar al cambio para que M <=> M == M, entonces usted puede hacer lo siguiente:

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

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