Mantis Bug Tracker

View Issue Details Jump to Notes ] Issue History ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0004172OCamlOCaml generalpublic2006-11-27 23:042014-02-17 16:44
Reporteracone 
Assigned Toweis 
PrioritynormalSeverityfeatureReproducibilityalways
StatusclosedResolutionfixed 
PlatformOSOS Version
Product Version 
Target VersionFixed in Version 
Summary0004172: Duplicated record names in distinct types
DescriptionIn OCaml, the following causes problems:

type t1 = {a:int; b:int}
type t2 = {a:string; c:string}
let make_t1() = {a=5; b=10}

It's clear to our eyes that make_t1 should return a t1, not a t2, but the compiler assumes that it returns a t2. It does this because I've used a label that's bound in t2 (namely 'a'), and t2 was declared later. So when I run this code I get a type error.

I understand that the compiler does not try to infer which of t1 or t2 is meant because this requires exponential time. I admit that exponential time is unacceptable, but I feel there are better solutions than simply defaulting to the most recently declared type.

1) (the slighly less crappy solution)
warn the user whenever a parameter in a record type declaration shadows a parameter in a previous record type declaration.

2) (the solution I'd prefer)
whenever an expression's type is not uniquely specified by parameter names, require the user to state it's type explicitly.
For example, the following would be allowed:

type t1 = {a:int; b:int}
type t2 = {a:string; b:string}
let print_t1 (x : t1) = printf "(%d, %d)" x.a x.b

But the following would produce an error message like "Expression type can not be determined from parameter names. Please state its type explicitly.":

type t1 = {a:int; b:int}
type t2 = {a:string; b:string}
let print_t1 x = printf "(%d, %d)" x.a x.b

It should *not* insist, as it currently does, that I wanted x to be a t2.
Additional InformationAs it stands, the lack of this feature is a reason I sometimes avoid Caml. The standard solution--to prefix each parameter with the type's name--results in ugly, unreadable code.

The fix I'm proposing would not affect the computational complexity of type inference. It would simply require explicit typing for expressions that should need it.
TagsNo tags attached.
Attached Files

- Relationships
related to 0005525resolvedgarrigue Resolving record fields using all specified fields 

-  Notes
(0004016)
weis (developer)
2007-04-16 01:18

The general solution to the problem you mentioned is general overloading, and this is well-known as a difficult feature in the context of type inference.

Unfortunately, none of the solutions you proposed are satisfactory:
 - ``solution'' 1) provides a warning to the programmer, which is good but does not solve the problem: you cannot reuse the same label in two distinct types.
 - ``solution'' 2) is not trivial given the current technology of the type-checking and type reconstruction engine.

I'm looking for a different and more general solution to this specific problem.

Paraphrasing the famous Fermat's note on the proof of his conjecture, I would say ``cum grano salis'': I think I have a marvelous solution to this problem, but this bug tracking system is not the place to expose it in detail!
(0004019)
mottl (reporter)
2007-04-16 16:10

My favored solution to this problem is to wrap the record type definitions into a module, e.g. instead of the tedious

  type t1 = { t1_field1 : ...; t1_field2 : ... }

you write:

  module T1 = struct
    type t = { field1 : ...; field2 : ... }
  end

Besides being able to just "open T1" to get access to the unprefixed field names of this particular record type, you can also use the following nice syntax for binding record values:

  let v =
    { T1.
      field1 = ...;
      field2 = ...;
    }

Hope that helps...
(0004123)
jm (reporter)
2007-07-27 06:56

> instead of the tedious
>
> type t1 = { t1_field1 : ...; t1_field2 : ... }

By the way, for those of us mastering the auto-completion tool of our text editor, this syntax improves our ability to fastly see and write the fields of a record, without our recalling of the doc.
Same thing apply to pattern matching changes/navigations.

> let v =
> { T1.
> field1 = ...;
> field2 = ...;
> }
Nice syntax, but not easy to match a given field with a simple regexp.

Moral: the less ambiguous, the better.
(0010925)
yallop (developer)
2014-02-12 22:27

This issue was fixed by the addition of record punning: make_t1 now creates a t1, as expected.

- Issue History
Date Modified Username Field Change
2006-11-27 23:04 acone New Issue
2007-04-16 01:18 weis Note Added: 0004016
2007-04-16 01:18 weis Assigned To => weis
2007-04-16 01:18 weis Status new => acknowledged
2007-04-16 16:10 mottl Note Added: 0004019
2007-07-27 06:56 jm Note Added: 0004123
2014-02-12 22:26 yallop Relationship added related to 0005525
2014-02-12 22:27 yallop Note Added: 0010925
2014-02-17 16:44 frisch Status acknowledged => closed
2014-02-17 16:44 frisch Resolution open => fixed


Copyright © 2000 - 2011 MantisBT Group
Powered by Mantis Bugtracker