{-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, RecordWildCards, ScopedTypeVariables #-}
module Comparisons where
import Control.Applicative
import Data.Monoid ((<>))
import qualified Rank2
import Text.Grampa
import Utilities (symbol)
class ComparisonDomain c e where
greaterThan :: c -> c -> e
lessThan :: c -> c -> e
equal :: c -> c -> e
greaterOrEqual :: c -> c -> e
lessOrEqual :: c -> c -> e
instance Ord c => ComparisonDomain c Bool where
greaterThan a b = a > b
lessThan a b = a < b
equal a b = a == b
greaterOrEqual a b = a >= b
lessOrEqual a b = a <= b
instance ComparisonDomain [Char] [Char] where
lessThan = infixJoin "<"
lessOrEqual = infixJoin "<="
equal = infixJoin "=="
greaterOrEqual = infixJoin ">="
greaterThan = infixJoin ">"
infixJoin :: String -> String -> String -> String
infixJoin rel a b = a <> rel <> b
data Comparisons c e f =
Comparisons{test :: f e,
term :: f c}
deriving (Show)
instance Rank2.Functor (Comparisons c e) where
f <$> g = g{test= f (test g),
term= f (term g)}
instance Rank2.Apply (Comparisons c e) where
g <*> h = Comparisons{test= test g `Rank2.apply` test h,
term= term g `Rank2.apply` term h}
instance Rank2.Applicative (Comparisons c e) where
pure f = Comparisons f f
instance Rank2.DistributiveTraversable (Comparisons c e)
instance Rank2.Distributive (Comparisons c e) where
cotraverse w f = Comparisons{test= w (test <$> f),
term= w (term <$> f)}
instance Rank2.Foldable (Comparisons c e) where
foldMap f g = f (test g) <> f (term g)
instance Rank2.Traversable (Comparisons c e) where
traverse f g = Comparisons
<$> f (test g)
<*> f (term g)
comparisons :: (ComparisonDomain c e, Alternative (p g String), MonoidParsing (p g)) =>
GrammarBuilder (Comparisons c e) g p String
comparisons Comparisons{..} =
Comparisons{
test= lessThan <$> term <* symbol "<" <*> term
<|> lessOrEqual <$> term <* symbol "<=" <*> term
<|> equal <$> term <* symbol "==" <*> term
<|> greaterOrEqual <$> term <* symbol ">=" <*> term
<|> greaterThan <$> term <* symbol ">" <*> term,
term= empty}