メモ''
-- f :: (a -> b) -> (c , d , e) f g = let a = g ([] :: [a]) b = g (0 :: Int) c = g ('1'::Char) in (a,b,c) {- 型推論させた時の結果 Couldn't match expected type `[a]' against inferred type `Char' Expected type: [a] -> t Inferred type: Char -> t1 Couldn't match expected type `Int' against inferred type `Char' Expected type: Int -> t Inferred type: Char -> t1 -} {- 上記型宣言を明示的に行った場合 Couldn't match expected type `[a]' against inferred type `Int' In the first argument of `g', namely `(0 :: Int)' In the expression: g (0 :: Int) In the definition of `b': b = g (0 :: Int) -}
うーん、これは宣言における型変数aは、1度適用した段階で実は固定される(単相性を持つようになる?)ので、引数として別の型を取る事が出来なく成ってしまうという事なんだろうか...。
例えば、gとしてidを渡したい場合に、id :: (a -> a)が(id []){id :: [a] -> [a]}、(id (0::Int)){id :: Int -> Int}、(id ('1'::Char)){id :: Char -> Char}の何れか(これは評価順で決まるのかな)に縛られちゃうっていう。
なんでこうなってるんかを考えねば。
http://www.sampou.org/haskell/report-revised-j/decls.html#4.5.5 単相性制限 通常の多相性に関する Hindley-Milner 制限は、その環境で束縛されて いない型変数のみが一般化できるというものである。
これで言う所の「束縛」が上記で発生しているのか、していないのかが分からん。そして、していないとすると何なんだろうという事だな。
let-bound polymorphism
http://www.haskell.org/tutorial/pitfalls.html
http://www.sampou.org/haskell/tutorial-j/pitfalls.html
どっちかというとこっちっぽいかな。
主型が a->a であるようなラムダ抽象に束縛された関数 g が f 内でふたつの別の方法でつかわれているからです。 一度は [a]->[a] という型で、そして、もう一度は Char->Char という型で使われています。