33

Making a ternary logic table, and I would like to make my own function for an operator that I'll call <=>.

So, for example, I want to do this, but that isn't right. what's the correct way to do this?

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
2
  • 4
    Just as a side note, M <=> M should be M rather than T. But that depends on your "Maybe" semantics. Commented Feb 20, 2012 at 6:06
  • Don't forget that you can set arity and associativity by using infixl, infixr... Commented Feb 20, 2012 at 8:31

4 Answers 4

51

Just add parentheses around your operator:

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

This turns it from infix form to prefix form. Alternatively, you can just use infix in the definition:

(<=>) :: 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
Sign up to request clarification or add additional context in comments.

3 Comments

Is there a way to create something like the : cons operator? The : cons operator has this special feature where it considers everything on the right hand side to be a list. I've been trying to recreate the : operator, but it always requires parentheses on the right hand side.
@ClarkGaebel: perhaps it might be interesting to mention infix as well?
@CMCDragonkai You can do the same thing yourself the following way: data List a = Nil | a :- List a and then the crucial part: infixr 5 :-. Doesn't have to be 5, but that is the precedence of lists, just has to be infixr and NOT infixl or infix. infixl 9 is the default
12

Function names with symbols have different syntax than those without:

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

I promise, though - Haskell is well worth learning the complex rules.

Comments

2

You can simplify (line-wise) the definition as follows:

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

3 Comments

That doesn't look simpler to me.
That's why I have a (line-wise) in there. Clarity is debatable though. I can see the code better because I am forced to deduce what it actually does as opposed to looking at a raw tabulated definition. But that's me.
IMO it is simpler, I can quickly see that if they are equal then return true, if they aren't but one is a maybe, then return maybe, if they aren't equal and don't involve a maybe then return false. Only part that I might find surprising is the M <=> M being T part.
1

Since you have Eq and Ord, you can do the following:

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

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

If you do happen to change it so that M <=> M == M, then you can do the following:

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

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.