Mailing list for all users of the OCaml language and system.
 help / color / mirror / Atom feed
* Re: Typing of patterns
@ 2000-06-06  7:24 Pierre Weis
  0 siblings, 0 replies; 8+ messages in thread
From: Pierre Weis @ 2000-06-06  7:24 UTC (permalink / raw)
  To: caml-list

[...]
> Ah - I think I see now: I was fooled by the syntactic "disguise" of the
> problem! So this is similar to:
> 
> This does not work:
> 
>   fun id -> id 42, id "foo"
> 
> This works:
> 
>   let id x = x in id 42, id "foo"

Exactly.

[...]
> So the restriction is required to prevent problems with references, I
> think, but those cannot occur if the type parameter is not used by any of
> the parameters of the constructor, i.e. they are monomorphic (or there are
> no parameters as in our case).

There is nothing special with references here: restriction for
references is just for generalization of types in let binding (roughly
speaking, when typing let x = e, x is monomorphic if e is an
application of the form f y). Here the restriction is just to be
correct: fun x -> x should have type 'a -> 'a, not 'a -> 'b; however
in case of complex pattern matching the rule is a bit too restrictive,
and can be relaxed in some cases as we saw.

> > Jacques may explain us if the above suggested generalization scheme is
> > used for identifiers bound in as clauses of patterns (and if not,
> > which scheme is used ?)...
> 
> I first thought it was some strange "special feature" of polymorphic
> variants, but as it seems then, it is just that the corresponding typing
> rule is obviously implemented differently...

I don't know if it is an implementation of the relaxed type-checking of
as identifiers or a special feature... Jacques will tell us...

[...]

> Since we are at it, there is another sometimes annoying type restriction,
> this time with record updates, that comes to my mind, e.g.:
> 
>   type 'a t = { foo : 'a; bar : int };;
> 
>   let x = { foo = "foo"; bar = 3 };;
> 
>   let ok = { x with foo = "bla" };;
>   let not_ok = { x with foo = 7 };;
> 
> Here the updated record "x" could have a less rigidly typed "foo"-field -
> or should we rather say it has a "default" type if the field is not
> updated? It can be a bit painful to do updates without such a
> generalisation if there are many record names that one would have to
> mention explicitely to create the wanted value as in:
> 
>   let now_ok = { foo = 7; bar = x.bar }

In some sense the problem is similar, since it is a problem of type
sharing. However it is a bit simpler in this case:

{ x with foo = "bla" } should be simply treated as a macro and typechecked
exactly as its equivalent unsuggared expression :

{foo = "bla"; bar = x.bar}

This would be more general and regular.

Best regards,

Pierre Weis

INRIA, Projet Cristal, Pierre.Weis@inria.fr, http://cristal.inria.fr/~weis/




^ permalink raw reply	[flat|nested] 8+ messages in thread
* Typing of patterns
@ 2000-06-01 13:23 Markus Mottl
  2000-06-05 13:56 ` Pierre Weis
  0 siblings, 1 reply; 8+ messages in thread
From: Markus Mottl @ 2000-06-01 13:23 UTC (permalink / raw)
  To: OCAML

Hello,

I would like to know something about the typing rules of identifiers that
are bound in pattern matching:

Let's consider this small example:

  module type FUNCTOR = sig
    type 'a t
    val map : ('a -> 'b) -> ('a t -> 'b t)
  end

  type 'a expr = Num of int | Add of 'a * 'a

  module ExprFun : FUNCTOR = struct
    type 'a t = 'a expr

    let map f = function
      | Num n as num -> num
      | Add (e, e') -> Add (f e, f e')
  end

This will lead to the (shortened) error message:

  Values do not match:
    val map : ('a -> 'a) -> 'a expr -> 'a expr
  is not included in
    val map : ('a -> 'b) -> 'a t -> 'b t

The problem arises in this line:

  | Num n as num -> num

This looks perfectly ok at first sight, but a closer look reveals that
"num" is not only bound to the value "Num n", it also has the exact type of
the left-hand side. Thus, the rhs will also be forced to have this type if
we use this pattern name.

To correct the problem, we can write:

  | Num n -> Num n

But isn't this a bit strange that an identifier cannot be used in a context
where replacing it syntactically with its bound value would be perfectly
ok?

Or has experience shown that using more general types in such cases leads
to more programming errors?

One can, of course, always explicitely restrict the type of an identifier,
but in the upper example we want to have the opposite, i.e. have it more
general. One side effect of this problem is that we cannot efficiently
return the value "as is": we have to construct it again, which may come
with a not insignficant performance penalty...

Are there any deeper insights behind this rationale? (The given code works
without problems if polymorphic variants are used instead).

Best regards,
Markus Mottl

-- 
Markus Mottl, mottl@miss.wu-wien.ac.at, http://miss.wu-wien.ac.at/~mottl




^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2000-06-06 15:37 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2000-06-06  7:24 Typing of patterns Pierre Weis
  -- strict thread matches above, loose matches on Subject: below --
2000-06-01 13:23 Markus Mottl
2000-06-05 13:56 ` Pierre Weis
2000-06-05 15:29   ` Markus Mottl
2000-06-06  0:55   ` Jacques Garrigue
2000-06-06 15:32     ` Pierre Weis
2000-06-06  1:10   ` Patrick M Doane
2000-06-06  8:55     ` Jacques Garrigue

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox