2

I'm trying to write Robinson's unification algorithm using recursion schemes. The unification algorithm takes two types and spits a result. A type is a:

data TypeF a
    = TypeApplication a a
    | TypeVariable Name
    deriving (Read,Show,Eq,Functor,Foldable,Traversable)
type Type = Fix TypeF

unify :: Type -> Type -> Result
unify = ...

How can this be done elegantly using recursion schemes?

user47376
  • 2,263
  • 3
  • 21
  • 26
  • 1
    What is `Result`? – Willem Van Onsem Sep 09 '17 at 12:03
  • A Substitution, but that doesn't really matter. – user47376 Sep 09 '17 at 12:07
  • think about your base cases - how should a `TypeVariable n` and a `TypeVariable m` unify? a `TypeVariable n` and a `TypeApplication x y`? a `TypeApplication x y` and a `TypeApplication u v`? – rampion Sep 09 '17 at 15:58
  • i) use the free monad rather than the raw fixpoint to distinguish variables from all other constructs (and to obtain a handy implementation of substitution); ii) learn about the halfZip operation (google it!); iii) note that any functor which is halfzippable and traversable induces a free monad with a Robinson unification algorithm – pigworker Sep 09 '17 at 16:28
  • Since @pigworker's Google search turns up a lot of clothing, you might look at https://stackoverflow.com/a/45254970/1477667 – dfeuer Sep 09 '17 at 18:18
  • halfZip Haskell narrows it down... – pigworker Sep 09 '17 at 21:09

1 Answers1

2

I'd just suggest currying and a hylomorphism.

data TypeF a
    = TypeApplication a a
    | TypeVariable Name
    deriving (Read,Show,Eq,Functor,Foldable,Traversable)
type Type = Fix TypeF

unify :: (Type, Type) -> Result
unify = hylo algebra coalgebra
    where algebra :: TypeF Result -> Result
          algebra = ...
          coalgebra :: (Type, Type) -> TypeF (Type, Type)
          coalgebra = ...

As an aside, I would probably with TypeF as follows, using the recursion-schemes package.

import Data.Functor.Foldable.TH (makeBaseFunctor)

data Type = TypeApplication Type Type
          | TypeVariable Name

makeBaseFunctor ''Type

This will automatically generate exactly what you want in this case, with no need to use to Fix.