{- -----------------------------------------------------------------------------
Copyright 2019-2020 Kevin P. Barry

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
----------------------------------------------------------------------------- -}

-- Author: Kevin P. Barry [ta0kira@gmail.com]

{-# LANGUAGE Safe #-}

module Types.Variance (
  Variance(..),
  allowsVariance,
  composeVariance,
) where


-- NOTE: The ordering here is used when prioritizing multiple constraints on an
-- inferred type.
data Variance =
  Contravariant |
  Covariant |
  Invariant
  deriving (Variance -> Variance -> Bool
(Variance -> Variance -> Bool)
-> (Variance -> Variance -> Bool) -> Eq Variance
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Variance -> Variance -> Bool
$c/= :: Variance -> Variance -> Bool
== :: Variance -> Variance -> Bool
$c== :: Variance -> Variance -> Bool
Eq,Eq Variance
Eq Variance
-> (Variance -> Variance -> Ordering)
-> (Variance -> Variance -> Bool)
-> (Variance -> Variance -> Bool)
-> (Variance -> Variance -> Bool)
-> (Variance -> Variance -> Bool)
-> (Variance -> Variance -> Variance)
-> (Variance -> Variance -> Variance)
-> Ord Variance
Variance -> Variance -> Bool
Variance -> Variance -> Ordering
Variance -> Variance -> Variance
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Variance -> Variance -> Variance
$cmin :: Variance -> Variance -> Variance
max :: Variance -> Variance -> Variance
$cmax :: Variance -> Variance -> Variance
>= :: Variance -> Variance -> Bool
$c>= :: Variance -> Variance -> Bool
> :: Variance -> Variance -> Bool
$c> :: Variance -> Variance -> Bool
<= :: Variance -> Variance -> Bool
$c<= :: Variance -> Variance -> Bool
< :: Variance -> Variance -> Bool
$c< :: Variance -> Variance -> Bool
compare :: Variance -> Variance -> Ordering
$ccompare :: Variance -> Variance -> Ordering
$cp1Ord :: Eq Variance
Ord)

instance Show Variance where
  show :: Variance -> String
show Variance
Contravariant = String
"contravariant"
  show Variance
Invariant     = String
"invariant"
  show Variance
Covariant     = String
"covariant"

composeVariance :: Variance -> Variance -> Variance
composeVariance :: Variance -> Variance -> Variance
composeVariance Variance
Covariant      Variance
Covariant      = Variance
Covariant
composeVariance Variance
Contravariant  Variance
Contravariant  = Variance
Covariant
composeVariance Variance
Contravariant  Variance
Covariant      = Variance
Contravariant
composeVariance Variance
Covariant      Variance
Contravariant  = Variance
Contravariant
composeVariance Variance
_              Variance
_              = Variance
Invariant

allowsVariance :: Variance -> Variance -> Bool
Variance
Covariant     allowsVariance :: Variance -> Variance -> Bool
`allowsVariance` Variance
Covariant     = Bool
True
Variance
Contravariant `allowsVariance` Variance
Contravariant = Bool
True
Variance
Invariant     `allowsVariance` Variance
_             = Bool
True
Variance
_             `allowsVariance` Variance
_             = Bool
False