@hackage unbound-generics-unify0.1.1

Unification based on unbound-generics

  • Categories

    • License

      BSD-3-Clause

    • Maintainer

      trupill@gmail.com

      Lottery factor: 0

    • Versions

    Unification for unbound-generics

    This package implements (first-order) unification by reusing the framework of unbound-generics.

    To use it, declare your data types as usual, including the generically-derived instances for alpha-equivalence (Alpha) and substitution (Subst) from unbound-generics. In addition to those, ask for a new instance of Unify with the same arguments as Subst, that is, the type from which we build variables, and the type we want to unify.

    The packages provides a function unify which works on a Unification monad. This monad is parametrized by the type we draw variables from. That means you can have as many types as you want, but there should be a single type of variables. In many cases the compiler fails to infer that argument to the Unification monad, so we recommend enabling TypeApplications for that matter.

    The result of unify is either a single value which is an instance of both arguments, or a UnificationError. That error explains where the process has failed by a Path consisting of constructor, fields, and indices; and a cause.


    This is an example in which Type is the one we draw variables from. Since we also use TypeConstructor inside the TyCon constructor, we also need to "request" to derive Unify Type TypeConstructor.

    type TypeVar = Name Type
    
    data Type = TyVar { var :: TypeVar }
              | TyFun { args :: [Type], ret :: Type }
              | TyCon { con :: TypeConstructor, args :: [Type] }
              deriving (Eq, Show, Generic, Typeable)
    
    data TypeConstructor = TyConInt | TyConBool deriving (Eq, Show, Generic)
    
    pattern TyInt, TyBool :: Type
    pattern TyInt  = TyCon TyConInt []
    pattern TyBool = TyCon TyConBool []
    
    instance Alpha Type
    instance Alpha TypeConstructor
    
    instance Subst Type Type where
      isvar (TyVar v) = Just $ SubstName v
      isvar _ = Nothing
    instance Subst Type TypeConstructor
    
    instance Unify Type Type
    instance Unify Type TypeConstructor
    

    Here are some example runs, using the explicitly-typed version of runUnification to declare that we are using Type-variables. To create new variables we use the usual s2n function from unbound-generics.

    >>> runUnification @Type $ let x = s2n "x" in unify' (TyFun [TyVar x] TyInt) (TyFun [TyVar x] (TyVar x))
    ( Right (TyFun {args = [TyCon {con = TyConInt, args = []}], ret = TyCon {con = TyConInt, args = []}})
    , fromList [(x,TyCon {con = TyConInt, args = []})] )
    
    >>> runUnification @Type $ let x = s2n "x" in unify' (TyFun [TyVar x] TyInt) (TyFun [TyBool] (TyVar x))
    ( Left ([PathConstructor "TyFun", PathSelector "ret", PathConstructor "TyCon", PathSelector "con"], DifferentConstructor)
    , fromList [(x,TyCon {con = TyConBool, args = []})] )