From b866a9bcc1ec7fa6c5d26410eb4c0e49e08795c9 Mon Sep 17 00:00:00 2001 From: simonpj Date: Wed, 23 Oct 2002 15:56:39 +0000 Subject: [PATCH] [project @ 2002-10-23 15:56:39 by simonpj] Document implicit parameter bindings --- ghc/docs/users_guide/glasgow_exts.sgml | 89 +++++++++++++++++++------------- 1 file changed, 54 insertions(+), 35 deletions(-) diff --git a/ghc/docs/users_guide/glasgow_exts.sgml b/ghc/docs/users_guide/glasgow_exts.sgml index 06e2a13..063527b 100644 --- a/ghc/docs/users_guide/glasgow_exts.sgml +++ b/ghc/docs/users_guide/glasgow_exts.sgml @@ -1555,10 +1555,12 @@ implicitly parameterized by a comparison function named cmp. The dynamic binding constraints are just a new form of predicate in the type class system. -An implicit parameter is introduced by the special form ?x, +An implicit parameter occurs in an exprssion using the special form ?x, where x is -any valid identifier. Use if this construct also introduces new -dynamic binding constraints. For example, the following definition +any valid identifier (e.g. ord ?x is a valid expression). +Use of this construct also introduces a new +dynamic-binding constraint in the type of the expression. +For example, the following definition shows how we can define an implicitly parameterized sort function in terms of an explicitly parameterized sortBy function: @@ -1567,6 +1569,11 @@ terms of an explicitly parameterized sortBy function: sort :: (?cmp :: a -> a -> Bool) => [a] -> [a] sort = sortBy ?cmp + + + +Implicit-parameter type constraints + Dynamic binding constraints behave just like other type class constraints in that they are automatically propagated. Thus, when a function is used, its implicit parameters are inherited by the @@ -1583,68 +1590,80 @@ propagated. With implicit parameters, the default is to always propagate them. -An implicit parameter differs from other type class constraints in the +An implicit-parameter type constraint differs from other type class constraints in the following way: All uses of a particular implicit parameter must have the same type. This means that the type of (?x, ?x) is (?x::a) => (a,a), and not (?x::a, ?x::b) => (a, b), as would be the case for type class constraints. + + You can't have an implicit parameter in the context of a class or instance +declaration. For example, both these declarations are illegal: + + class (?x::Int) => C a where ... + instance (?x::a) => Foo [a] where ... + +Reason: exactly which implicit parameter you pick up depends on exactly where +you invoke a function. But the ``invocation'' of instance declarations is done +behind the scenes by the compiler, so it's hard to figure out exactly where it is done. +Easiest thing is to outlaw the offending types. + + + +Implicit-parameter bindings + -An implicit parameter is bound using the standard -let binding form, where the bindings must be a -collection of simple bindings to implicit-style variables (no -function-style bindings, and no type signatures); these bindings are -neither polymorphic or recursive. This form binds the implicit -parameters arising in the body, not the free variables as a -let or where would do. For -example, we define the min function by binding -cmp. +An implicit parameter is bound using the standard +let or where binding forms. +For example, we define the min function by binding +cmp. min :: [a] -> a min = let ?cmp = (<=) in least + +A group of implicit-parameter bindings may occur anywhere a normal group of Haskell +bindings can occur, except at top level. That is, they can occur in a let +(including in a list comprehension, or do-notation, or pattern guards), +or a where clause. Note the following points: +An implicit-parameter binding group must be a +collection of simple bindings to implicit-style variables (no +function-style bindings, and no type signatures); these bindings are +neither polymorphic or recursive. + + You may not mix implicit-parameter bindings with ordinary bindings in a single let expression; use two nested lets instead. +(In the case of where you are stuck, since you can't nest where clauses.) You may put multiple implicit-parameter bindings in a -single let expression; they are not treated +single binding group; but they are not treated as a mutually recursive group (as ordinary let bindings are). -Instead they are treated as a non-recursive group, each scoping over the bindings that -follow. For example, consider: +Instead they are treated as a non-recursive group, simultaneously binding all the implicit +parameter. The bindings are not nested, and may be re-ordered without changing +the meaning of the program. +For example, consider: - f y = let { ?x = y; ?x = ?x+1 } in ?x + f t = let { ?x = t; ?y = ?x+(1::Int) } in ?x + ?y -This function adds one to its argument. - - - -You may not have an implicit-parameter binding in a where clause, -only in a let binding. - - - - You can't have an implicit parameter in the context of a class or instance -declaration. For example, both these declarations are illegal: +The use of ?x in the binding for ?y does not "see" +the binding for ?x, so the type of f is - class (?x::Int) => C a where ... - instance (?x::a) => Foo [a] where ... + f :: (?x::Int) => Int -> Int -Reason: exactly which implicit parameter you pick up depends on exactly where -you invoke a function. But the ``invocation'' of instance declarations is done -behind the scenes by the compiler, so it's hard to figure out exactly where it is done. -Easiest thing is to outlaw the offending types. - + + -- 1.7.10.4