ランク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
解説を後で書く時間があるといいなあ。