Growth of Type Definition in SML Using Hindley Milner Type Inference

Someone once showed me a little 'trick' in SML where they wrote out about 3 or 4 functions in their REPL and the resulting type for the last value was extremely long (like many page scrolls long).

Does anyone know what code generates such a long type, or if there is a name for this kind of behavior?


The types that are inferred by Hindley/Milner type inference can become exponentially large if you compose them in the right way. For example:

fun f x = (x, x, x)
val t = f (f (f (f (f 0))))

Here, t is a nested triple, whose nesting depth corresponds to the number n of invocations of f . Consequently, the overall type has size 3^n.

However, this is not actually the worst case, since the type has a regular structure and can be represented by a graph efficiently in linear space (because on each level, all three constituent types are the same and can be shared).

The real worst case uses polymorphic instantiation to defeat this:

fun f x y z = (x, y, z)
val p1 = (f, f, f)
val p2 = (p1, p1, p1)
val p3 = (p2, p2, p2)

In this case, the type is again exponentially large, but unlike above, all constituent types are different fresh type variables, so that even a graph representation grows exponentially (in the number of pN declarations).

So yes, Hindley/Milner-style type inference is worst-case exponential (in space and time). It is worth pointing out, however, that the exponential cases can only occur where types get exponentially large -- ie in cases, that you cannot even realistically express without type inference.

链接地址: http://www.djcxy.com/p/80886.html

上一篇: Rust如何解决Hindley的可变性问题

下一篇: 用HindleyMilner型推理在SML中定义类型定义的增长