ランク1多相性

http://d.hatena.ne.jp/succeed/20061026#1161853372

知っていて書いている:-)のかもしれませんが、これ↓を「きちんと動く」とは言えない、という考え方なのでしょう。

# let f x y = (x, y) ;;
val f : 'a -> 'b -> 'a * 'b = <fun>
# let f1 = f 1 ;;
val f1 : '_a -> int * '_a = <fun>
# f1 2 ;;
- : int * int = (1, 2)
# f1 ;;
- : int -> int * int = <fun>
# f1 true ;;
Characters 3-7:
  f1 true ;;
     ^^^^
This expression has type bool but is here used with type int

参考:

> smlsharp
restoring static environment...done
restoring dynamic environment...done
# fun f x y = (x, y) ;
val f = fn : ['a .'a  -> ['b .'b  -> 'a * 'b]]
# val f1 = f 1 ;
val f1 = fn : ['a .'a  -> int * 'a]
# f1 2 ;
val it = ( 1, 2 ) : int * int
# f1 ;
val it = fn : ['a .'a  -> int * 'a]
# f1 true ;
val it = ( 1, true ) : int * bool

Cf. http://www.pllab.riec.tohoku.ac.jp/smlsharp/
http://www.pllab.riec.tohoku.ac.jp/~ohori/research/icfp99.pdf

そういえば、これ↑やレコード多相を例のコンパイラ演習で実装したという人もいました。
追記:こっちのほうがわかりやすいかも。

> cat foo.ml
let f x y = (x, y)
let f1 = f 1
> ocamlc foo.ml
File "foo.ml", line 2, characters 9-12:
The type of this expression, '_a -> int * '_a,
contains type variables that cannot be generalized
> sml
Standard ML of New Jersey, Version 110.0.7, September 28, 2000 [CM; autoload enabled]
- let fun f x y = (x, y)
=     val f1 = f 1
= in f1 2
= end ;
val it = (1,2) : int * int

追記2:さらに混乱させてみる。(Cf. http://www.math.nagoya-u.ac.jp/~garrigue/papers/morepoly-long.pdf)

# let f x = [] ;;
val f : 'a -> 'b list = <fun>
# let y = f 1 ;;
val y : 'a list = []
# (1 :: y, true :: y) ;;
- : int list * bool list = ([1], [true])
> sml
Standard ML of New Jersey, Version 110.0.7, September 28, 2000 [CM; autoload enabled]
- fun f x = [] ;
val f = fn : 'a -> 'b list
- val y = f 1 ;
stdIn:18.1-18.12 Warning: type vars not generalized because of
   value restriction are instantiated to dummy types (X1,X2,...)
val y = [] : ?.X1 list
- 1 :: y ;
stdIn:19.1-19.7 Error: operator and operand don't agree [literal]
  operator domain: int * int list
  operand:         int * ?.X1 list
  in expression:
    1 :: y
> smlsharp
restoring static environment...done
restoring dynamic environment...done
# fun f x = [] ;
val f = fn : ['a .'a  -> ['b .'b list]]
# val y = f 1 ;
val y = [] : ['a .'a list]
# (1 :: y, true :: y) ;
val it = ( [1], [true] ) : int list * bool list

解説を後で書く時間があるといいなあ