问题
I have this expression in SML and need to find the most general type of it. When run through the compiler I get what it shows below. How would I go about finding what the most general type would be of not only this function but other functions like church numerals function "two".
val one = fn f => (fn x => f x)
Why is the type of this:
('a -> 'b) -> 'a -> 'b
回答1:
What you do is, you apply a process called Hindley–Milner type inference.
The general principle involves three steps:
First, we assign undetermined types (written
'Z,'Y,'X, etc.) to variables and expressions.- If the expression uses a variable that we've already assigned a type to, then we use that. For example, if
threehas already been bound with typeint, then inval nine = three * three, we know that thethreehas typeint. - If the expression uses a variable that we've already assigned a nontrivial type scheme to (i.e., it's polymorphic), then we use that scheme, but replace each type variable with an undetermined type. For example, if
firsthas already been bound with type'a * 'b -> 'a, then inval firstOfFirst = fn quartet => first (first quartet), we assign onefirstthe type'Z * 'Y -> 'Zand the other one the type'X * 'W -> 'W. - If the expression uses a newly-bound variable (scoped by
fnorrec), then all occurrences of that variable have to have exact the same type — no polymorphism is allowed at this point. For example, infn f => (f 1, f "one")(which ends up giving a type error), we initially assign all occurrences offthe single type'Z. (The type error results because we later need to refine that to bothint -> 'Yandstring -> 'Y, and these are contradictory. This is because Standard ML doesn't support first-class polymorphism.)
In your example,
val one = fn f => (fn x => f x), we can assignfthe type'Z, andxthe type'Y.- If the expression uses a variable that we've already assigned a type to, then we use that. For example, if
Next, we perform type unification, where we identify different parts of the types of different sub-expressions that have to match. For example, if we know that
fhas type'Z -> realand thatihas typeint, then if we seef i, we can "unify" the'Zwith theintand conclude thatfhas typeint -> real.- There are many, many details of type unification, but I think they're all pretty much what you would assume, so I won't go into them.
In your example, since
fis applied tox, we can unify'Zwith'Y -> ..., and end up assigningfthe type'Y -> 'X. So the expression as a whole has type('Y -> 'X) -> 'Y -> 'X.Lastly, we perform type generalization. Once we've performed all unifications that can be performed — once we've deduced everything we can about the types — we can safely replace the undetermined types with bound type variables. In your case, that lets us assign
onethe type-scheme ∀ αβ . (α → β) → α → β (meaning "for any and all types α and β,onehas the type (α → β) → α → β"). In Standard ML notation, we don't include the explicit "∀ αβ" part; we just write('a -> 'b) -> 'a -> 'b.
回答2:
I don't really understand your question, so I am just guessing ...
If I define the first church numeral functions in the REPL:
val c0 = fn f => fn x => x
val c1 = fn f => fn x => f x
val c2 = fn f => fn x => f (f x)
val c3 = fn f => fn x => f (f (f x))
val c4 = fn f => fn x => f (f (f (f x)))
... and then look at their types:
val c0 = fn : 'a -> 'b -> 'b
val c1 = fn : ('a -> 'b) -> 'a -> 'b
val c2 = fn : ('a -> 'a) -> 'a -> 'a
val c3 = fn : ('a -> 'a) -> 'a -> 'a
val c4 = fn : ('a -> 'a) -> 'a -> 'a
... after the 2nd function the type ('a ->'a) -> 'a -> 'a emerges. Is this the general type you are looking for?
The type of the first two functions differs only because the type inference algorithm chooses the most general type. And for the first function 'a -> 'b -> 'b is a more general type as ('a -> 'a) -> 'a -> 'a. But you can always give the compiler a hint using a type annotation:
val c0 : ('a -> 'a) -> 'a -> 'a = fn f => fn x => x
val c1 : ('a -> 'a) -> 'a -> 'a = fn f => fn x => f x
... and all your functions should have the same type now.
来源:https://stackoverflow.com/questions/28594801/sml-church-numeral-type-inference