Safe Haskell | None |
---|
Gory details for GeniVal
- data GeniVal = GeniVal {}
- mkGConst :: FullList Text -> GeniVal
- mkGConstNone :: Text -> GeniVal
- mkGVar :: Text -> Maybe (FullList Text) -> GeniVal
- mkGVarNone :: Text -> GeniVal
- mkGAnon :: GeniVal
- singletonVal :: GeniVal -> Maybe Text
- isAnon :: GeniVal -> Bool
- type Subst = Map Text GeniVal
- prettySubst :: Subst -> Text
- class (MonadPlus m, MonadError Text m, Monad m, Functor m) => MonadUnify m
- unify :: MonadUnify m => [GeniVal] -> [GeniVal] -> m ([GeniVal], Subst)
- allSubsume :: MonadUnify m => [GeniVal] -> [GeniVal] -> m ([GeniVal], Subst)
- unifyHelper :: (MonadError Text m, Monad m) => (GeniVal -> GeniVal -> UnificationResult) -> [GeniVal] -> [GeniVal] -> m ([GeniVal], Subst)
- appendSubst :: Subst -> Subst -> Subst
- prependToSubst :: (Text, GeniVal) -> Subst -> Subst
- data UnificationResult
- unifyOne :: GeniVal -> GeniVal -> UnificationResult
- intersectConstraints :: Eq a => Maybe (FullList a) -> Maybe (FullList a) -> Maybe (Maybe (FullList a))
- subsumeOne :: GeniVal -> GeniVal -> UnificationResult
- replace :: DescendGeniVal a => Subst -> a -> a
- replaceOne :: DescendGeniVal a => (Text, GeniVal) -> a -> a
- replaceList :: DescendGeniVal a => [(Text, GeniVal)] -> a -> a
- replaceMapG :: Subst -> GeniVal -> GeniVal
- replaceOneG :: (Text, GeniVal) -> GeniVal -> GeniVal
- type CollectedVar = (Text, Maybe (FullList Text))
- class Collectable a where
- collect :: a -> Map CollectedVar Int -> Map CollectedVar Int
- class Idable a where
- anonymiseSingletons :: (Collectable a, DescendGeniVal a) => a -> a
- finaliseVarsById :: (Collectable a, DescendGeniVal a, Idable a) => a -> a
- finaliseVars :: (Collectable a, DescendGeniVal a) => Text -> a -> a
- newtype SchemaVal = SchemaVal [GeniVal]
- crushOne :: SchemaVal -> Maybe GeniVal
- crushList :: [SchemaVal] -> Maybe [GeniVal]
- class DescendGeniVal a where
- descendGeniVal :: (GeniVal -> GeniVal) -> a -> a
Documentation
data GeniVal
- constant : no label, just constraints
- variable : label, with or without constraints
- anonymous : no label, no constraints
GeniVal | |
|
Eq GeniVal | |
Data GeniVal | |
Ord GeniVal | |
Typeable GeniVal | |
Binary GeniVal | |
NFData GeniVal | |
Pretty GeniVal | |
Pretty SemInput | |
Pretty Sem | |
GeniShow GeniVal | |
GeniShow SemInput | |
GeniShow LitConstr | |
GeniShow Sem | |
DescendGeniVal GeniVal | |
Collectable GeniVal | |
HasConstants GeniVal | |
GeniValLike GeniVal | |
Pretty (FeatStruct GeniVal) | |
Pretty (AvPair GeniVal) | |
Pretty (Flist GeniVal) | |
Pretty (Literal GeniVal) | |
Pretty (GNode GeniVal) | The default show for GNode tries to be very compact; it only shows the value for cat attribute and any flags which are marked on that node. This is one the places where the pretty representation of a GenI object is different from its GenI-format one |
GeniShow (FeatStruct GeniVal) | |
GeniShow (Literal GeniVal) | |
HasConstants (Literal GeniVal) |
mkGConstNone :: Text -> GeniVal
Create a singleton constant (no disjunction here)
mkGVarNone :: Text -> GeniVal
Create a variable with no constraints
singletonVal :: GeniVal -> Maybe Text
If v
has exactly one value/constraint, returns it
A variable substitution map. GenI unification works by rewriting variables
prettySubst :: Subst -> Text
For debugging
class (MonadPlus m, MonadError Text m, Monad m, Functor m) => MonadUnify m
allSubsume :: MonadUnify m => [GeniVal] -> [GeniVal] -> m ([GeniVal], Subst)
l1
returns the result of allSubsume
l2l1
if
doing a simultaneous traversal of both lists, each item in
unify
l2l1
subsumes the corresponding item in l2
unifyHelper :: (MonadError Text m, Monad m) => (GeniVal -> GeniVal -> UnificationResult) -> [GeniVal] -> [GeniVal] -> m ([GeniVal], Subst)
unifyHelper unf gs1 gs2
zips two lists with some unification function.
It's meant to serve as a helper to unify
and allSubsume
appendSubst :: Subst -> Subst -> Subst
Note that the first Subst is assumed to come chronologically
before the second one; so merging { X -> Y }
and { Y -> 3 }
should give us { X -> 3; Y -> 3 }
;
See prependToSubst
for a warning!
prependToSubst :: (Text, GeniVal) -> Subst -> Subst
Add to variable replacement to a Subst
that logical comes before
the other stuff in it. So for example, if we have Y -> foo
and we want to insert X -> Y
, we notice that, in fact, Y
has
already been replaced by foo
, so we add X -> foo
instead
Note that it is undefined if you try to append something like
Y -> foo
to Y -> bar
, because that would mean that unification
is broken
data UnificationResult
Unification can either…
SuccessSans GeniVal | succeed for free (no substitutions), |
SuccessRep Text GeniVal | succeed with a one-way substitution, |
SuccessRep2 Text Text GeniVal | succeed w both vars needing substitution (constraint intersection), |
Failure | or fail |
unifyOne :: GeniVal -> GeniVal -> UnificationResult
See source code for details
Note that we assume that it's acceptable to generate new
variable names by appending an x
to them; this assumption
is only safe if the variables have gone through the function
finaliseVarsById
or have been pre-processed and rewritten
with some kind of common suffix to avoid an accidental match
intersectConstraints :: Eq a => Maybe (FullList a) -> Maybe (FullList a) -> Maybe (Maybe (FullList a))
intersectConstraints (Just cs1) (Just cs2)
returns the intersection of
cs1
and cs2
if non-empty (or Nothing
if there's nothing in common)
If any of the arguments is unconstrained (Nothing
), we simply return
the other.
subsumeOne :: GeniVal -> GeniVal -> UnificationResult
subsumeOne
x y
returns the same result as unifyOne x y
if x
subsumes y
or Failure
otherwise
Variable substitution
replace :: DescendGeniVal a => Subst -> a -> a
Apply variable substitutions
replaceOne :: DescendGeniVal a => (Text, GeniVal) -> a -> a
Apply a single variable substitution
replaceList :: DescendGeniVal a => [(Text, GeniVal)] -> a -> a
Here it is safe to say (X -> Y; Y -> Z) because this would be crushed down into a final value of (X -> Z; Y -> Z)
replaceMapG :: Subst -> GeniVal -> GeniVal
Core implementation for replace
For use by the Uniplate-esq descendGeniVal
replaceOneG :: (Text, GeniVal) -> GeniVal -> GeniVal
Core implementation for replaceOne
For use by the Uniplate-esq descendGeniVal
Variable collection and renaming
type CollectedVar = (Text, Maybe (FullList Text))
A variable label and its constraints
class Collectable a where
A Collectable
is something which can return its variables as a
map from the variable to the number of times that variable occurs
in it.
Important invariant: if the variable does not occur, then it does not appear in the map (ie. all counts must be >= 1 or the item does not occur at all)
By variables, what I most had in mind was the GVar values in a GeniVal. This notion is probably not very useful outside the context of alpha-conversion task, but it seems general enough that I'll keep it around for a good bit, until either some use for it creeps up, or I find a more general notion that I can transform this into.
collect :: a -> Map CollectedVar Int -> Map CollectedVar Int
collect x m
increments our count for any variables in x
(adds not-yet-seen variables as needed)
Collectable SchemaVal | |
Collectable GeniVal | |
Collectable LexEntry | |
Collectable TagElem | |
Collectable UninflectedDisjunction | |
Collectable a => Collectable [a] | |
Collectable a => Collectable (Maybe a) | |
Collectable a => Collectable (Tree a) | |
Collectable a => Collectable (AvPair a) | |
Collectable a => Collectable (Literal a) | |
Collectable gv => Collectable (GNode gv) | |
Collectable a => Collectable (Ttree a) |
class Idable a where
An Idable is something that can be mapped to a unique id. You might consider using this to implement Ord, but I won't. Note that the only use I have for this so far (20 dec 2005) is in alpha-conversion.
anonymiseSingletons :: (Collectable a, DescendGeniVal a) => a -> a
Anonymise any variable that occurs only once in the object
finaliseVarsById :: (Collectable a, DescendGeniVal a, Idable a) => a -> a
finaliseVarsById
appends a unique suffix to all variables in
an object. This avoids us having to alpha convert all the time
and relies on the assumption finding that a unique suffix is
possible.
finaliseVars :: (Collectable a, DescendGeniVal a) => Text -> a -> a
finaliseVars
does the following:
- (if suffix is non-null) appends a suffix to all variable names to ensure global uniqueness
- intersects constraints for for all variables within the same object
Fancy disjunction
newtype SchemaVal
A schema value is a disjunction of GenI values. It allows us to express
“fancy” disjunctions in tree schemata, ie. disjunctions over variables
and not just atoms (?X;?Y
).
Our rule is that that when a tree schema is instantiated, any fancy
disjunctions must be “crushed” into a single GeniVal
lest it be
rejected (see crushOne
)
Note that this is still not recursive; we don't have disjunction over
schema values, nor can schema values refer to schema values. It just
allows us to express the idea that in tree schemata, you can have
either variable ?X
or ?Y
.
crushOne :: SchemaVal -> Maybe GeniVal
Convert a fancy disjunction (allowing disjunction over variables) value into a plain old atomic disjunction. The idea is to support a limited notion of fancy disjunction by requiring that there be a single point where this disjunction can be converted into a plain old variable. Note that we currently convert these to constants only.
Genericity
class DescendGeniVal a where
A structure that can be traversed with a GeniVal
-replacing
function (typical use case: substitution after unification)
Approach suggested by Neil Mitchell after I found that Uniplate seemed to hurt GenI performance a bit.
descendGeniVal :: (GeniVal -> GeniVal) -> a -> a
descendGeniVal f x
applies f
to all GeniVal
in x
DescendGeniVal SchemaVal | |
DescendGeniVal GeniVal | |
DescendGeniVal LexEntry | |
DescendGeniVal TagElem | |
DescendGeniVal TagSite | |
DescendGeniVal UninflectedDisjunction | |
DescendGeniVal SimpleItem | |
(Functor f, DescendGeniVal a) => DescendGeniVal (f a) | |
DescendGeniVal v => DescendGeniVal (AvPair v) | |
DescendGeniVal a => DescendGeniVal (Literal a) | |
DescendGeniVal v => DescendGeniVal (GNode v) | |
DescendGeniVal v => DescendGeniVal (Ttree v) | |
DescendGeniVal v => DescendGeniVal ([String], Flist v) | |
DescendGeniVal a => DescendGeniVal (String, a) | |
DescendGeniVal (Text, UninflectedDisjunction) | |
DescendGeniVal a => DescendGeniVal (Map k a) |