简体   繁体   中英

Generalized HM vs. Higher-Order Unification

AFAIK, unification used in the Hindley-Milner type system can be generalized to unify higher-kinded types by allowing type vars in constructor position and by relaxing the arity constraint in such cases:

f a ~ T a1 b1
f ~ T a1 -- generatifity + partial application
a ~ b1   -- injectivity

I guess kinds are also involved, but I don't know how.

With my little experience I'd say this is enough for a sound unification of higher-kinded types. The main differences to higher-order unification are probably

  • generalized HM is decidable, HOU is not in general
  • generalized HM is more restricted, ie rejects types that are legal in HOU

While I somehow answered my question what higher-order unification gives us, I don't have a clue what (simplified) rules are involved when higher-order unification is applied. How does the algorithm differ from generalized HM?

This isn't really my wheelhouse, but I can maybe offer a very general answer.

The fundamental difference is that generalized HM treats unification as a purely syntactic matching process aimed at producing a unique match, while an HOU algorithm involves a semantic consideration of the types/kinds (as terms/types in a typed lambda calculus) and a systematic search through a tree of possible unifications, including consideration of alternative unifications at interior nodes.

(The reason for the limitations of the HM approach is that for first-order types, purely syntactic matching is basically equivalent to a semantic consideration of the types and a systematic search through possibly unifications.)

Anyway, take a trivial higher-order unification:

Either String Int ~ f String

Your proposed generalized HM algorithm fails on this unification for the absurd reason that Either 's arguments are in the wrong order, a purely syntactic detail that has nothing to do with the types' semantic unifiability. You could further generalize your algorithm to handle this particular case syntactically, but there would invariably be some other trivial unification that wouldn't match the syntactic pattern. You'd also end up with a bizarre "discontinuity" at the unification:

Either String String ~ f String

You'd be able to get your algorithm to type-check a program with unifications:

Either Int String ~ f Int
Either String String ~ f String
 ==> f x = Either x String

or:

Either String Int ~ f Int
Either String String ~ f String
 ==> f x = Either String x

but presumably not both.

In contrast, any self-respecting HOU algorithm would have no trouble type-checking these programs.

HOU algorithms based on Huet's algorithm do so by constructing a "matching tree". Each node in the tree is labelled with a "disagreement set" (basically, a set of unresolved unifications), with branches labelled with alternative substitutions. Terminal nodes indicate "success" or "failure" of the unification.

Example 3.2 presented in Huet's paper is the unification:

f x A ~ B

Any generalized HM would immediately give up, as the type B , being of kind * , can't syntactically unify with a type expression involving f:: * -> * -> * .

For a Huet-like algorithm, the matching tree is constructed with this singleton disagreement set at the root node with three possible kind-correct substitutions for f on its branches:

f :: * -> * -> *
f u v = u
f u v = v
f u v = B

giving the tree:

                        f x A ~ B
                             |
        --------------------------------------------
        | (f u v = u)        | (f u v = v)         | (f u v = B)
        |                    |                     |
      x ~ B              Failure                 Success
        |
        | (x = B)
        |
      Success

If you give it a moment's consideration, you'll see that the power of a generalized HM type checker versus an HOU checker isn't even remotely comparable. You'll also see that an HOU type checker in practice can be a power that a programmer might find hard to control. It's maybe a little hard to reason about a type checker that can deduce either fx = Either x String or fx = Either String x .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM