How do I create an operator in Haskell?
Asked Answered
P

4

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
Punctilio answered 20/2, 2012 at 5:8 Comment(2)
Just as a side note, M <=> M should be M rather than T. But that depends on your "Maybe" semantics.Aufmann
Don't forget that you can set arity and associativity by using infixl, infixr...Jeffers
D
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
Drugget answered 20/2, 2012 at 5:10 Comment(3)
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.Quasi
@ClarkGaebel: perhaps it might be interesting to mention infix as well?Paco
@Quasi 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 defaultTracytrade
A
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.

Abyssinia answered 20/2, 2012 at 6:1 Comment(0)
N
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
Noblesse answered 20/2, 2012 at 18:33 Comment(3)
That doesn't look simpler to me.Drugget
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.Noblesse
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.Tracytrade
U
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
Uprise answered 24/2, 2012 at 2:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.