Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Misleading comment on private type abbreviations #6548

Closed
vicuna opened this issue Sep 9, 2014 · 3 comments
Closed

Misleading comment on private type abbreviations #6548

vicuna opened this issue Sep 9, 2014 · 3 comments

Comments

@vicuna
Copy link

vicuna commented Sep 9, 2014

Original bug ID: 6548
Reporter: pveber
Assigned to: @Octachron
Status: resolved (set by @Octachron on 2017-05-08T21:24:18Z)
Resolution: fixed
Priority: normal
Severity: minor
Version: 4.02.0+beta1 / +rc1
Fixed in version: 4.06.0 +dev/beta1/beta2/rc1
Category: documentation
Tags: junior_job
Related to: #6589

Bug description

In "Language extensions", paragraph 7.9.2 says that

"For ambiguity reasons, typexpr cannot be an object or polymorphic variant type, but a similar behaviour can be obtained through private row types."

Actually private row types behave in a different way than what would be expected from private type abbreviation of a polymorphic variant:

module T

: sig type t = private [> a | b] end
= struct type t = [a | b] end
;;
module T : sig type t = private [> a | b ] end

let f (x : T.t) = match x with | a -> true | b -> false;;

Characters 18-57:
Warning 8: this pattern-matching is not exhaustive. Here is an example of a value that is not matched:
`AnyExtraTag
val f : T.t -> bool =

That is, exhaustivity check is not possible any more with private row types. The limitation of this workaround should be indicated, and other workarounds could be suggested:

  • defining an auxiliary type:

module T
: sig type t = private u and u = [ a | b] end
= struct type t = [a | b] and u = t end;;

  • using abstract types :

module T
: sig type t val repr : t -> [a | b] end
= struct type t = [a | b] let repr x = x end
;;

@vicuna
Copy link
Author

vicuna commented Sep 9, 2014

Comment author: @lpw25

"For ambiguity reasons, typexpr cannot be an object or polymorphic variant type, but a similar behaviour can be obtained through private row types."

This sentence should indeed be removed, but not for the reason suggested. It should be removed because this limitation was removed in version 4.02:

# type t = private [ `A | `B ];;
type t = private [ `A | `B ]

Actually private row types behave in a different way than what would be expected from private type abbreviation of a polymorphic variant:

module T

: sig type t = private [> a | b] end
= struct type t = [a | b] end
;;
module T : sig type t = private [> a | b ] end

let f (x : T.t) = match x with | a -> true | b -> false;;

Characters 18-57:
Warning 8: this pattern-matching is not exhaustive. Here is an example of a value that is not matched:
`AnyExtraTag
val f : T.t -> bool =

That is, exhaustivity check is not possible any more with private row types.

This exhaustivity check is not failing because t is a private row type, it is failing because it is an open row type. I believe that you instead wanted a closed row type:

type t = private [< `A | `B ];; (* Note < not > *)

Then the exhaustivity check passes as you wanted.

Also note that with a regular private type abbreviation you cannot match directly on the abbreviated type, but must instead use a coercion:

# type t = private [ `A | `B ];;
type t = private [ `A | `B ]

# let f (x : t) = match x with `A -> 4 | _ -> 5;;
Characters 29-31:
  let f (x : t) = match x with `A -> 4 | _ -> 5;;
                               ^^
Error: This pattern matches values of type [? `A ]
       but a pattern was expected which matches values of type t

# let f (x : t) = match (x :> [ `A | `B ] ) with `A -> 4 | _ -> 5;;
val f : t -> int = <fun>

So it is actually private type abbreviations that are more restricted than private row types.

@vicuna
Copy link
Author

vicuna commented Sep 9, 2014

Comment author: pveber

Thanks a lot Leo for this explanation. It solves my initial problem well: I'll indeed use a private row type, but a closed one.

Also I'm glad I found a bug in the documentation, even if for a totally wrong reason ;o).

@vicuna
Copy link
Author

vicuna commented May 8, 2017

Comment author: @Octachron

The obsolete remark on the limitations of private type abbreviations was removed from the manual by integrating #1165 .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants