Copyright | (C) 2018-19 Carlo Nucera |
---|---|
License | BSD-style (see the file LICENSE) |
Maintainer | Carlo Nucera <meditans@gmail.com> |
Stability | experimental |
Portability | non-portable |
Safe Haskell | None |
Language | Haskell2010 |
Generic.Unification.Substitution
Contents
Description
This module mainly defines Substitution
s and related operations, and a
typeclass Substitutable
to apply substitutions and get free variables.
Synopsis
- newtype Substitution = Substitution (TypeRepMap (Constrained WellFormed (IntMap :.: Term)))
- class (Eq a, Eq (Term a), Show (Term a), Substitutable a) => WellFormed (a :: Type)
- data Constrained c f a = c a => Constrained (f a)
- withConstrained :: (forall x. c x => f x -> r) -> Constrained c f a -> r
- empty :: Substitution
- insert :: forall a. (WellFormed a, Typeable a) => Int -> Term a -> Substitution -> Substitution
- singleton :: forall a. (WellFormed a, Typeable a) => Int -> Term a -> Substitution
- lookup :: forall a. Typeable a => Int -> Substitution -> Maybe (Term a)
- union :: Substitution -> Substitution -> Substitution
- fold :: forall m. Monoid m => (forall x. WellFormed x => Term x -> m) -> Substitution -> m
- substFreeVars :: Substitution -> FreeVars
- class Substitutable a where
- newtype FreeVars = FreeVars (TypeRepMap (Const IntSet :: Type -> Type))
- memberFreeVars :: forall (a :: Type). Typeable a => Int -> FreeVars -> Bool
- freeVarsOfType :: forall a b. (Typeable a, Substitutable b) => Term b -> [Term a]
- newtype Visited = Visited (TypeRepMap (Const IntSet :: Type -> Type))
- memberVisited :: forall (a :: Type). Typeable a => Int -> Visited -> Bool
- insertVisited :: forall (a :: Type). Typeable a => Int -> Visited -> Visited
Substitutions
newtype Substitution #
Substitutions map variables (internally represented as Ints) to Terms of a specific type. A key design principle of this library is that each type has its set of variables, that do not overlap. So in the following substitution the variable 1 of type Char tracks the term `Con c` while the variable 1 of type Int tracks the term `Con 42`. There is no possibility of ambiguity, and this simplifies the definition of Term.
>>>
:set -XTypeApplications
>>>
ex_substitution = insert @Char 1 (Con 'c') . insert @Int 1 (Con 42) $ empty :: Substitution
>>>
ex_substitution
Substitution { Int -> [(1,Con 42)], Char -> [(1,Con 'c')] }
Constructors
Substitution (TypeRepMap (Constrained WellFormed (IntMap :.: Term))) |
Instances
class (Eq a, Eq (Term a), Show (Term a), Substitutable a) => WellFormed (a :: Type) #
This is a class that expresses the constraint we need every type in our substitution to have. It is an implementation detail of the library, but helps in understanding which datatype we can have in our substitutions.
Instances
(Eq a, Eq (Term a), Show (Term a), Substitutable a) => WellFormed a # | |
Defined in Generic.Unification.Substitution |
data Constrained c f a #
A datatype that includes a constraint (this is useful because, as a substitution contains heterogeneous terms, we have to be sure that those terms have some common behaviour to be able to operate on them, and we use Constrained to assure that).
Constructors
c a => Constrained (f a) |
withConstrained :: (forall x. c x => f x -> r) -> Constrained c f a -> r #
The generic eliminator for Constrained
Operations on substitutions
empty :: Substitution #
The empty substitution, which does not contain variable bindings
>>>
empty
Substitution { }
insert :: forall a. (WellFormed a, Typeable a) => Int -> Term a -> Substitution -> Substitution #
Insert a variable binding into a substitution
>>>
:set -XTypeApplications
>>>
insert @Int 1 (Con 42) empty
Substitution { Int -> [(1,Con 42)] }
singleton :: forall a. (WellFormed a, Typeable a) => Int -> Term a -> Substitution #
A substitution with only one variable binding
>>>
:set -XTypeApplications
>>>
singleton @Int 1 (Con 42)
Substitution { Int -> [(1,Con 42)] }
lookup :: forall a. Typeable a => Int -> Substitution -> Maybe (Term a) #
Search for a variable in the substitution
>>>
lookup @Int 1 $ singleton @Int 1 (Con 42)
Just (Con 42)>>>
lookup @String 1 $ singleton @Int 1 (Con 42)
Nothing
union :: Substitution -> Substitution -> Substitution #
The union of two substitutions. It has the same bias of union in Data.Map, if you think a substitution as a [(Type, Value)] map-like structure
>>>
union (singleton @Int 1 (Con 42)) (singleton @Char 1 (Con 'c'))
Substitution { Int -> [(1,Con 42)], Char -> [(1,Con 'c')] }
fold :: forall m. Monoid m => (forall x. WellFormed x => Term x -> m) -> Substitution -> m #
We can fold a substitution in a monoidal value
>>>
fold (\a -> [show a]) (insert @Char 1 (Con 'c') . insert @Int 1 (Con 42) $ empty)
["Con 42","Con 'c'"]
substFreeVars :: Substitution -> FreeVars #
Take all variables that are free in a substitution. This amounts to taking all the free variables of the internal terms
The Substitutable class
class Substitutable a where #
This class means that we can calculate the free variables of something and apply to it a substitution. The default instance signatures appear duplicated for a bug of haddock.
Minimal complete definition
Nothing
Methods
(@@) :: Substitution -> Term a -> Maybe (Term a) #
Apply a substitution to a term. This is also where we check for a cycle to occur, as we don't do the occur check in the unification algorithm to speed it up.
(@@) :: (Typeable a, All2 Substitutable (Code a), Generic a) => Substitution -> Term a -> Maybe (Term a) #
Apply a substitution to a term. This is also where we check for a cycle to occur, as we don't do the occur check in the unification algorithm to speed it up.
Calculate the free variables of a term.
ftv :: (Typeable a, All2 Substitutable (Code a), Generic a) => Term a -> FreeVars #
Calculate the free variables of a term.
Instances
Substitutable Char # | |
Substitutable Int # | |
(Typeable a, All2 Substitutable (Code a), Generic a) => Substitutable a # | |
Other type-indexed structures
Free Variables
This datatype encodes the free (not bound) variables that we can have in a term or a substitution. Basically, since our variables are overlappable, a set of variables for every type.
>>>
FreeVars (fromList [TM.WrapTypeable @Int $ Const (IS.fromList [1,2]), TM.WrapTypeable @Char $ Const (IS.fromList [1,3])])
FreeVars { Int -> [1,2], Char -> [1,3] }
Usually one would get a FreeVars
from using the method ftv
of the
Substitutable class.
>>>
ftv (Var 1 :: Term Int)
FreeVars { Int -> [1] }
memberFreeVars :: forall (a :: Type). Typeable a => Int -> FreeVars -> Bool #
We can query if a variable is in the FreeVars at a certain type
>>>
:set -XTypeApplications
>>>
memberFreeVars @Int 1 (ftv (Var 1 :: Term Int))
True>>>
memberFreeVars @Int 1 (ftv (Var 1 :: Term Char))
False
freeVarsOfType :: forall a b. (Typeable a, Substitutable b) => Term b -> [Term a] #
Get all the free variables of a type, as variables of that term. This is made to implement the equivalent of prolog's term_variables.
Visited Sets
Visited sets: an abstraction in the Dijkstra paper that let us avoid
expensive occurs check in the substitution process, substituting it with
checking visited sets when the substitution is applied. This datatype is
representationally equivalent to FreeVars
, ie. it is only a IntSet
for
every type.
>>>
Visited (fromList [TM.WrapTypeable @Int $ Const (IS.fromList [1,2]), TM.WrapTypeable @Char $ Const (IS.fromList [1,3])])
Visited { Int -> [1,2], Char -> [1,3] }
This datatype is only meant to be used in the library, the user shouldn't need it.