[[project @ 2005-03-09 10:54:57 by simonpj]
simonpj**20050309105457
Add notes about implicit parameters; pls merge
] {
hunk ./ghc/docs/users_guide/glasgow_exts.xml 2110
+
+
+Implicit parameters and polymorphic recursion
+
+
+Consider these two definitions:
+
+ len1 :: [a] -> Int
+ len1 xs = let ?acc = 0 in len_acc1 xs
+
+ len_acc1 [] = ?acc
+ len_acc1 (x:xs) = let ?acc = ?acc + (1::Int) in len_acc1 xs
+
+ ------------
+
+ len2 :: [a] -> Int
+ len2 xs = let ?acc = 0 in len_acc2 xs
+
+ len_acc2 :: (?acc :: Int) => [a] -> Int
+ len_acc2 [] = ?acc
+ len_acc2 (x:xs) = let ?acc = ?acc + (1::Int) in len_acc2 xs
+
+The only difference between the two groups is that in the second group
+len_acc is given a type signature.
+In the former case, len_acc1 is monomorphic in its own
+right-hand side, so the implicit parameter ?acc is not
+passed to the recursive call. In the latter case, because len_acc2
+has a type signature, the recursive call is made to the
+polymoprhic version, which takes ?acc
+as an implicit parameter. So we get the following results in GHCi:
+
+ Prog> len1 "hello"
+ 0
+ Prog> len2 "hello"
+ 5
+
+Adding a type signature dramatically changes the result! This is a rather
+counter-intuitive phenomenon, worth watching out for.
+
+
+
+Implicit parameters and monomorphism
+
+GHC applies the dreaded Monomorphism Restriction (section 4.5.5 of the
+Haskell Report) to implicit parameters. For example, consider:
+
+ f :: Int -> Int
+ f v = let ?x = 0 in
+ let y = ?x + v in
+ let ?x = 5 in
+ y
+
+Since the binding for y falls under the Monomorphism
+Restriction it is not generalised, so the type of y is
+simply Int, not (?x::Int) => Int.
+Hence, (f 9) returns result 9.
+If you add a type signature for y, then y
+will get type (?x::Int) => Int, so the occurrence of
+y in the body of the let will see the
+inner binding of ?x, so (f 9) will return
+14.
+
}