lol-typing-1.20160822: Language/LOL/Typing/Type/Qualification.hs
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# OPTIONS_GHC -fno-warn-tabs #-}
module Language.LOL.Typing.Type.Qualification where
import Data.Eq (Eq)
import qualified Data.Foldable as Foldable
import Data.Function (($), (.))
import Data.Functor (Functor(..), (<$>))
import qualified Data.List as List
import Data.Monoid (Monoid(..), (<>))
import Text.Show (Show(..))
import Data.Text.Buildable (Buildable(..))
import Language.LOL.Typing.Type.Monotype
import Language.LOL.Typing.Type.Substitution
import Language.LOL.Typing.Type.Quantification
-- * Type 'Qualification'
-- | A 'Qualification' introduces constraints on 'Monotype_Var's.
--
-- Example: the qualified 'Polytype': @forall a. Eq a => [a] -> [a]@
-- restricts @a@ to the members of the 'Class' @Eq@.
--
-- Example: @forall a b. (a ~ b) => a -> b@
-- could be an alternative formulation for the 'Polytype'
-- of the /identity function/.
data Qualification qs a
= Qualification
{ qualifiers :: qs
, qualified :: a
} deriving (Eq, Show)
-- | Qualify the 'subvars' of given 'a' (except those in given @context@)
-- with given @[qualifier]@.
qualify_but ::
( Substitutable qualifier
, Substitutable a
) => [Monovar] -> [qualifier] -> a
-> Qualification [qualifier] a
qualify_but vars_mono quals qualified =
Qualification
{ qualifiers = List.filter is_quantified quals
, qualified
}
where
vars_poly = subvars qualified List.\\ vars_mono
is_quantified = Foldable.any (`List.elem` vars_poly) . subvars
instance Functor (Qualification qt) where
fmap f q = q{qualified = f (qualified q)}
instance Buildable q => Buildable
( Quantification_Build_Options
, Qualification [q] Monotype
) where
build (_opts, q) = build q
instance
( Substitutable q
, Substitutable a
) => Substitutable (Qualification q a) where
subvars q = subvars (qualifiers q) `List.union` subvars (qualified q)
sub `substitute` q = Qualification
{ qualifiers = sub `substitute` qualifiers q
, qualified = sub `substitute` qualified q
}
instance (Has_Monotypes q, Has_Monotypes a) => Has_Monotypes (Qualification q a) where
monotypes = monotypes . qualifiers
monotypes_map f q = Qualification
{ qualifiers = monotypes_map f $ qualifiers q
, qualified = monotypes_map f $ qualified q
}
instance (Buildable q, Buildable a)
=> Buildable (Qualification [q] a) where
build Qualification{qualifiers, qualified} =
(case qualifiers of
[] -> ""
[q] -> build q <> " => "
_ -> "(" <> mconcat (List.intersperse ", " $ build <$> qualifiers) <> ") => "
) <>
build qualified