Portability | semi-portable (MPTCs, fundeps,...) |
---|---|
Stability | experimental |
Maintainer | wren@community.haskell.org |
This module defines the classes and primitive types used by unification and related functions.
- data MutTerm v t
- freeze :: Traversable t => MutTerm v t -> Maybe (Fix t)
- unfreeze :: Functor t => Fix t -> MutTerm v t
- data UnificationFailure v t
- = OccursIn (v (MutTerm v t)) (MutTerm v t)
- | TermMismatch (t (MutTerm v t)) (t (MutTerm v t))
- | UnknownError String
- class Traversable t => Unifiable t where
- class Variable v where
- class (Unifiable t, Variable v, Applicative m, Monad m) => BindingMonad v t m | m -> v t where
- data Rank v t = Rank !Word8 !(Maybe (MutTerm v t))
- class BindingMonad v t m => RankedBindingMonad v t m | m -> v t where
- lookupRankVar :: v (MutTerm v t) -> m (Rank v t)
- incrementRank :: v (MutTerm v t) -> m ()
- incrementBindVar :: v (MutTerm v t) -> MutTerm v t -> m ()
Mutable terms
freeze :: Traversable t => MutTerm v t -> Maybe (Fix t)Source
O(n). Extract a pure term from a mutable term, or return
Nothing
if the mutable term actually contains variables. N.B.,
this function is pure, so you should manually apply bindings
before calling it.
Errors
data UnificationFailure v t Source
The possible failure modes that could be encountered in unification and related functions. While many of the functions could be given more accurate types if we used ad-hoc combinations of these constructors (i.e., because they can only throw one of the errors), the extra complexity is not considered worth it.
OccursIn (v (MutTerm v t)) (MutTerm v t) | A cyclic term was encountered (i.e., the variable
occurs free in a term it would have to be bound to in
order to succeed). Infinite terms like this are not
generally acceptable, so we do not support them. In logic
programming this should simply be treated as unification
failure; in type checking this should result in a "could
not construct infinite type Note that since, by default, the library uses visited-sets instead of the occurs-check these errors will be thrown at the point where the cycle is dereferenced/unrolled (e.g., when applying bindings), instead of at the time when the cycle is created. However, the arguments to this constructor should express the same context as if we had performed the occurs-check, in order for error messages to be intelligable. |
TermMismatch (t (MutTerm v t)) (t (MutTerm v t)) | The top-most level of the terms do not match (according
to |
UnknownError String | Required for the |
(Show (t (MutTerm v t)), Show (v (MutTerm v t))) => Show (UnificationFailure v t) | |
Error (UnificationFailure v t) |
Basic type classes
class Traversable t => Unifiable t whereSource
An implementation of unification variables. Note that we do
not require variables to be functors. Thus, it does not matter
whether you give them vacuous functor instances, or use clever
tricks like CoYoneda STRef
to give them real functor instances.
eqVar :: v a -> v b -> BoolSource
Determine whether two variables are equal as variables, without considering what they are bound to. The default implementation is:
eqVar x y = getVarID x == getVarID y
Return a unique identifier for this variable, in order to support the use of visited-sets instead of occurs-checks.
class (Unifiable t, Variable v, Applicative m, Monad m) => BindingMonad v t m | m -> v t whereSource
The basic class for generating, reading, and writing to bindings stored in a monad. These three functionalities could be split apart, but are combined in order to simplify contexts. Also, because most functions reading bindings will also perform path compression, there's no way to distinguish "true" mutation from mere path compression.
The superclass constraints are there to simplify contexts, since
we make the same assumptions everywhere we use BindingMonad
.
lookupVar :: v (MutTerm v t) -> m (Maybe (MutTerm v t))Source
Given a variable pointing to MutTerm v t
, return the
term it's bound to, or Nothing
if the variable is unbound.
freeVar :: m (v (MutTerm v t))Source
Generate a new free variable guaranteed to be fresh in
m
.
newVar :: MutTerm v t -> m (v (MutTerm v t))Source
Generate a new variable (fresh in m
) bound to the given
term. The default implementation is:
newVar t = do { v <- freeVar ; bindVar v t ; return v }
bindVar :: v (MutTerm v t) -> MutTerm v t -> m ()Source
Bind a variable to a term, overriding any previous binding.
(Unifiable t, Applicative m, Monad m) => BindingMonad IntVar t (IntBindingT t m) | |
(Unifiable t, Applicative m, Monad m) => BindingMonad IntVar t (IntRBindingT t m) | |
Unifiable t => BindingMonad (STVar s) t (STBinding s) | |
Unifiable t => BindingMonad (STRVar s t) t (STRBinding s) |
Weighted path compression
The target of variables for RankedBindingMonad
s. In order
to support weighted path compression, each variable is bound to
both another term (possibly) and also a "rank" which is related
to the length of the variable chain to the term it's ultimately
bound to.
The rank can be at most log V
, where V
is the total number
of variables in the unification problem. Thus, A Word8
is
sufficient for 2^(2^8)
variables, which is far more than can
be indexed by getVarID
even on 64-bit architectures.
class BindingMonad v t m => RankedBindingMonad v t m | m -> v t whereSource
An advanced class for BindingMonad
s which also support
weighted path compression. The weightedness adds non-trivial
implementation complications; so even though weighted path
compression is asymptotically optimal, the constant factors may
make it worthwhile to stick with the unweighted path compression
supported by BindingMonad
.
lookupRankVar :: v (MutTerm v t) -> m (Rank v t)Source
Given a variable pointing to MutTerm v t
, return its
rank and the term it's bound to.
incrementRank :: v (MutTerm v t) -> m ()Source
Increase the rank of a variable by one.
incrementBindVar :: v (MutTerm v t) -> MutTerm v t -> m ()Source
Bind a variable to a term and increment the rank at the same time. The default implementation is:
incrementBindVar v t = do { incrementRank v ; bindVar v t }
(Unifiable t, Applicative m, Monad m) => RankedBindingMonad IntVar t (IntRBindingT t m) | |
Unifiable t => RankedBindingMonad (STRVar s t) t (STRBinding s) |