Last active
October 31, 2015 00:33
-
-
Save CMCDragonkai/b97de3dd75a367dbed47 to your computer and use it in GitHub Desktop.
Haskell: Ternary Comparison Operators (inspired by ternary choice operator http://zenzike.com/posts/2011-08-01-the-conditional-choice-operator)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{- | |
The comparison operators are non-associative and not composable. | |
Thus it is illegal to write: 1 < 2 < 3 | |
The input types of < (Int) does not match the output type (Bool). | |
1 < 2 < 3 can however be written in math notation, because it denotes: | |
(1 < 2) && (2 < 3) or (1 < 2) ^ (2 < 3) | |
It is however possible to create a new ternary operator that supports such a | |
notation! | |
-} | |
-- right hand side | |
-- less | |
(.<) :: (Ord a) => a -> a -> (a, Bool) | |
b .< c | b < c = (b, True) | |
| b >= c = (b, False) | |
-- greater | |
(.>) :: (Ord a) => a -> a -> (a, Bool) | |
b .> c | b > c = (b, True) | |
| b <= c = (b, False) | |
-- less or equal | |
(.<=) :: (Ord a) => a -> a -> (a, Bool) | |
b .<= c | b <= c = (b, True) | |
| b > c = (b, False) | |
-- greater or equal | |
(.>=) :: (Ord a) => a -> a -> (a, Bool) | |
b .>= c | b >= c = (b, True) | |
| b < c = (b, False) | |
-- left hand side | |
-- less | |
(<.) :: (Ord a) => a -> (a, Bool) -> Bool | |
a <. (b, True) | a < b = True | |
| a >= b = False | |
_ <. (_, False) = False | |
-- greater | |
(>.) :: (Ord a) => a -> (a, Bool) -> Bool | |
a >. (b, True) | a > b = True | |
| a <= b = False | |
_ >. (_, False) = False | |
-- less or equal | |
(<=.) :: (Ord a) => a -> (a, Bool) -> Bool | |
a <=. (b, True) | a <= b = True | |
| a > b = False | |
_ <=. (_, False) = False | |
-- greater or equal | |
(>=.) :: (Ord a) => a -> (a, Bool) -> Bool | |
a >=. (b, True) | a >= b = True | |
| a < b = False | |
_ >=. (_, False) = False | |
infixr 0 .< | |
infixr 0 .> | |
infixr 0 .<= | |
infixr 0 .>= | |
infixr 0 <. | |
infixr 0 >. | |
infixr 0 <=. | |
infixr 0 >=. | |
-- 1 <. 2 .< 3 -- True | |
-- 3 >. 2 .> 1 -- True | |
-- 1 <. 4 .> 2 -- True | |
-- 2 >. 1 .< 3 -- True | |
-- 1 <=. 1 .<= 1 -- True | |
-- 2 >=. 1 .>= 1 -- True | |
{- | |
As these operators are right associative/fixity, this means | |
1 <. 2 .< 3 == 1 <. (2 .< 3) | |
-} | |
{- | |
However the implementation above is still not composable. It can be made | |
composable by chaining Maybe a types, but it is no longer a ternary operator. | |
This would require a Just constructor at the very end, and a special | |
operator at the beginning that will turn the Maybe a types into a booleans. | |
-} | |
(@<) :: (Ord a) => a -> Maybe a -> Maybe a | |
b @< Just c | b < c = Just b | |
| b >= c = Nothing | |
_ @< Nothing = Nothing | |
(<@) :: (Ord a) => a -> Maybe a -> Bool | |
a <@ Just b | a < b = True | |
| a >= b = False | |
_ <@ Nothing = False | |
infixr 0 @< | |
infixr 0 <@ | |
1 <@ 2 @< 3 @< 5 @< 6 @< Just 8 -- True |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment