# Pattern matching on private strings

**URL:** https://discuss.ocaml.org/t/pattern-matching-on-private-strings/1581
**Category:** Community
**Tags:** type-system
**Created:** [February 15, 2018, 7:42pm UTC](https://discuss.ocaml.org/t/pattern-matching-on-private-strings/1581 "2018-02-15T19:42:23Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![Chris00](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/chris00/32/48_2.png) [@Chris00](https://discuss.ocaml.org/u/Chris00)
#### Post date: [February 15, 2018, 7:42pm UTC](https://discuss.ocaml.org/t/pattern-matching-on-private-strings/1581/1 "2018-02-15T19:42:23Z")

</div>

Hi,

I was wondering why pattern matching on private strings with literal strings is disallowed while, if the string goes through a constructor, there is no problem. Here is an illustration of what I have in mind:

```ocaml
module A : sig
  type t = private string
end = struct
  type t = string
end

module B : sig
  type t = private S of string
end = struct
  type t = S of string
end

module C : sig
  type t = private S of string [@@unboxed]
end = struct
  type t = S of string [@@unboxed]
end

let f : A.t -> bool = function
  | "a" -> true
  | _ -> false

let g : B.t -> bool = function
  | B.S "a" -> true
  | _ -> false

let h : C.t -> bool = function
  | C.S "a" -> true
  | _ -> false

```

`g` and `h` can be defined without problem while `f` generated the error:

```auto
Error: This pattern matches values of type string
       but a pattern was expected which matches values of type A.t

```

---

<div class="post-metadata">

### Author: ![mjambon](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/mjambon/32/6180_2.png) [@mjambon](https://discuss.ocaml.org/u/mjambon)
#### Post date: [February 15, 2018, 9:07pm UTC](https://discuss.ocaml.org/t/pattern-matching-on-private-strings/1581/2 "2018-02-15T21:07:17Z")

</div>

I’m guessing there might be difficulties related to type inference. The type of the pattern `B.S _` is unambiguous while the type of `"a"` could be `string` or a `private string`.

---

<div class="post-metadata">

### Author: ![kantian](https://avatars.discourse-cdn.com/v4/letter/k/4bbf92/32.png) [@kantian](https://discuss.ocaml.org/u/kantian)
#### Post date: [February 15, 2018, 10:14pm UTC](https://discuss.ocaml.org/t/pattern-matching-on-private-strings/1581/3 "2018-02-15T22:14:01Z")

</div>

I don’t know the reason (and indeed this is strange) but you can define `f` by coercing an `A.t` to a `string`:

```ocaml
let f (x:A.t) = match (x :> string) with
  | "a" -> true
  | _ -> false;;
val f : A.t -> bool = <fun>

```

---

<div class="post-metadata">

### Author: ![Levi\_Roth](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/levi_roth/32/2268_2.png) [@Levi\_Roth](https://discuss.ocaml.org/u/Levi_Roth)
#### Post date: [February 15, 2018, 10:33pm UTC](https://discuss.ocaml.org/t/pattern-matching-on-private-strings/1581/4 "2018-02-15T22:33:53Z")

</div>

Per the manual, `private` has somewhat different behavior in variant and record declarations, type abbreviations, and row types: [OCaml - Language extensions](https://caml.inria.fr/pub/docs/manual-ocaml/extn.html#sec236)

For variants:

> Values of a variant or record type declared private can be de-structured normally in pattern-matching or via the _expr_`.`_field_ notation for record accesses.

On the other hand, for a type abbreviation you have to coerce the expression.

That being said, I don’t know if there’s a principled reason _why_ you can’t have the variant-declaration behavior w/r/t pattern matching when the type abbreviation is for a variant type. After all, you can always just coerce it and then match, right?

---

<div class="post-metadata">

### Author: ![Chris00](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/chris00/32/48_2.png) [@Chris00](https://discuss.ocaml.org/u/Chris00)
#### Post date: [February 15, 2018, 10:41pm UTC](https://discuss.ocaml.org/t/pattern-matching-on-private-strings/1581/5 "2018-02-15T22:41:22Z")

</div>

> let f (x:A.t) = match (x :\> string) with  
> | “a” → true  
> | \_ → false;;

Thanks but, in the case I’m targeting, `A.t` isn’t naked but itself an argument of another constructor (say `X of A.t`) on which I want to pattern match (`| X "a" -> ...`).

---

<div class="post-metadata">

### Author: ![mjambon](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/mjambon/32/6180_2.png) [@mjambon](https://discuss.ocaml.org/u/mjambon)
#### Post date: [February 15, 2018, 11:44pm UTC](https://discuss.ocaml.org/t/pattern-matching-on-private-strings/1581/6 "2018-02-15T23:44:15Z")

</div>

It’s really neat that variant (or record) constructors can be [disambiguated](http://gallium.inria.fr/blog/resolving-field-names/) with a type annotation. It’s also interesting that other types with ambiguous constructors like private strings are not disambiguated in the same way.

```auto
module Module : sig
  type private_string = private string
  type original_variant = X
end = struct
  type private_string = string
  type original_variant = X
end

type shadowing_variant = X

(* "a" is inferred as a string *)
let f1 = function "a" -> () | _ -> ()

(* error *)
let f2 = function ("a" : Module.private_string) -> () | _ -> ()

(* warning (which can be disabled) *)
let f3 = function (X : Module.original_variant) -> ()

```

---

<div class="post-metadata">

### Author: ![mjambon](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/mjambon/32/6180_2.png) [@mjambon](https://discuss.ocaml.org/u/mjambon)
#### Post date: [February 15, 2018, 11:52pm UTC](https://discuss.ocaml.org/t/pattern-matching-on-private-strings/1581/7 "2018-02-15T23:52:03Z")

</div>

Perhaps this example is clearer:

```auto
module Module : sig
  type private_string = private string
end = struct
  type private_string = string
end

(* Maybe this could put the private string constructor in scope? *)
open Module

type original_variant = X
type shadowing_variant = X

(* "a" is inferred as a string *)
let f1 = function "a" -> () | _ -> ()

(* error explaining that "a" is a string, not a private_string *)
let f2 = function ("a" : private_string) -> () | _ -> ()

(* ok *)
let f3 = function (X : original_variant) -> ()

```

---

<div class="post-metadata">

### Author: ![gsg](https://avatars.discourse-cdn.com/v4/letter/g/858c86/32.png) [@gsg](https://discuss.ocaml.org/u/gsg)
#### Post date: [February 16, 2018, 5:10am UTC](https://discuss.ocaml.org/t/pattern-matching-on-private-strings/1581/8 "2018-02-16T05:10:29Z")

</div>

> Thanks but, in the case I’m targeting, A.t isn’t naked but itself an argument of another constructor

You can use guards as a somewhat ugly work around for that case:

```
module A : sig
  type t = private string
end = struct
  type t = int
end

type t = X of A.t

let f = function
  | X s when (s :> string) = "a" -> true
  | _ -> false

```

If you are willing to parameterise the type containing the constructor in question, you can also coerce before matching:

```
type 'a t = X of 'a

let f (x : A.t t) =
  match (x :> string t) with
  | X "a" -> true
  | _ -> false

```

This isn’t a very nice solution because it involves adding one type parameter for each private type, of which there might be many. Might be enough to get you past this particular problem, though.

---

<div class="post-metadata">

### Author: ![UnixJunkie](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/unixjunkie/32/638_2.png) [@UnixJunkie](https://discuss.ocaml.org/u/UnixJunkie)
#### Post date: [February 16, 2018, 6:37am UTC](https://discuss.ocaml.org/t/pattern-matching-on-private-strings/1581/9 "2018-02-16T06:37:16Z")

</div>

there is a bitstring matching library for OCaml (bitstring in opam). I wonder if it could be extended to handle regular strings.

---

<div class="post-metadata">

### Author: ![kantian](https://avatars.discourse-cdn.com/v4/letter/k/4bbf92/32.png) [@kantian](https://discuss.ocaml.org/u/kantian)
#### Post date: [February 16, 2018, 2:21pm UTC](https://discuss.ocaml.org/t/pattern-matching-on-private-strings/1581/10 "2018-02-16T14:21:37Z")

</div>

In this case you have to pattern-match on the coerced value of your `A.t` behind your constructor. Example:

```ocaml
module A : sig type t = private string end = struct type t = string end

type t = A of int | B of A.t

let f = function
  | A i -> i
  | B s -> match (s :> string) with
    | "a" -> 1
    | "b" -> 2
    | _ -> 3

f (B (Obj.magic "a"));;
- : int = 1

f (B (Obj.magic "b"));;
- : int = 2

f (B (Obj.magic "a string"));;
- : int = 3

```

---

<div class="post-metadata">

### Author: ![mjambon](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/mjambon/32/6180_2.png) [@mjambon](https://discuss.ocaml.org/u/mjambon)
#### Post date: [February 16, 2018, 7:34pm UTC](https://discuss.ocaml.org/t/pattern-matching-on-private-strings/1581/11 "2018-02-16T19:34:00Z")

</div>

I believe a general feature that would solve this problem and more is [F#'s active patterns](https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/active-patterns). If I understand correctly, we’d write something like this:

```auto
let (|String|) (s : private_string) = (s :> string)

let f (s : private_string) =
  match s with
  | String "a" -> ...

```

---

<div class="post-metadata">

### Author: ![Chris00](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/chris00/32/48_2.png) [@Chris00](https://discuss.ocaml.org/u/Chris00)
#### Post date: [February 16, 2018, 10:56pm UTC](https://discuss.ocaml.org/t/pattern-matching-on-private-strings/1581/12 "2018-02-16T22:56:02Z")

</div>

> [@kantian](#):
>
> In this case you have to pattern-match on the coerced value of your A.t behind your constructor.

That does not work when you have more “complex” pattern matching such as

```auto
| Node(loc, B "a") -> do_something
| Node(_, B "b") -> do_something_else

```

---

<div class="post-metadata">

### Author: ![kantian](https://avatars.discourse-cdn.com/v4/letter/k/4bbf92/32.png) [@kantian](https://discuss.ocaml.org/u/kantian)
#### Post date: [February 16, 2018, 11:20pm UTC](https://discuss.ocaml.org/t/pattern-matching-on-private-strings/1581/13 "2018-02-16T23:20:07Z")

</div>

In this case you can use a guard as suggested by @gsg:

```ocaml
| Node (loc, B s) when (s :> string) = "a" -> do_something
| Node (_, B s) when (s :> string) = "b" -> do_something_else

```

A private type abbreviation is considered as a strict subtype of the type it abbreviates, hence you have to _explicitly_ coerce your value to pattern-match against them (otherwise the type checker will complain). It may be possible to change the compiler in such a way that the coercion will be done _implicitly_, but for the moment you don’t have the choice.

---

<div class="post-metadata">

### Author: ![Chris00](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/chris00/32/48_2.png) [@Chris00](https://discuss.ocaml.org/u/Chris00)
#### Post date: [February 17, 2018, 12:02am UTC](https://discuss.ocaml.org/t/pattern-matching-on-private-strings/1581/14 "2018-02-17T00:02:41Z")

</div>

> [@kantian](#):
>
> In this case you can use a guard

That’s what I started to do but it becomes fairly quickly not so nice to read IMHO. I prefer to go through a constructor.

---

<div class="post-metadata">

### Author: ![lpw25](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/lpw25/32/144_2.png) [@lpw25](https://discuss.ocaml.org/u/lpw25)
#### Post date: [February 18, 2018, 9:29pm UTC](https://discuss.ocaml.org/t/pattern-matching-on-private-strings/1581/15 "2018-02-18T21:29:24Z")

</div>

Some of the answers here are quite confused. This difference comes from the `private` keyword being used for three different but similar things:

1. It can define a variant or record type whose constructors are only allowed in pattern matching:

```ocaml
type t = private T of int

```

which will allow you to match on a `t` with `T` but not construct one.
2. It can define a polymorphic variant or object type with abstract row/presence variables.

```ocaml
type t = private [< `A of int | `B of int > `B]

```

which will unify with `[< `A of int | `B of int]` allowing you to pattern match with ``A` or ``B`, and also with `[> `B of int]` allowing you to construct with ``B`, but not with `[> `A of int]` so you cannot construct with `` `A`
3. It can define an arbitrary subtype of another type:

```ocaml
type t = private int

```

which gives a type that can be coerced to `int` with the `:>` operator.

The difficulty you are having is that OCaml does not support a coercion operator in patterns. Really you should be able to write something like:

```ocaml
type t = private int
type s = A of t
let f = function
  | A (4 : int <: t) -> ...

```

I believe @trefis has a patch that adds such an operator, but it has never been polished and submitted upstream.

---

<div class="post-metadata">

### Author: ![kantian](https://avatars.discourse-cdn.com/v4/letter/k/4bbf92/32.png) [@kantian](https://discuss.ocaml.org/u/kantian)
#### Post date: [February 19, 2018, 6:42pm UTC](https://discuss.ocaml.org/t/pattern-matching-on-private-strings/1581/16 "2018-02-19T18:42:29Z")

</div>

> [@lpw25](#):
>
> The difficulty you are having is that OCaml does not support a coercion operator in patterns.

Wouldn’t it be simple to authorize matching a literal with one of its subtype? For example, with these types:

```ocaml
module A : sig type t = private string end = struct type t = string end

type t = Empty | Node int * A.t

```

if I want to pattern-match against a `t` value in a “complex” pattern, I have to write:

```ocaml
let f = function
  | Empty -> 1
  | Node (i, a) -> match i, (a :> string) with
    | 1, "a" -> 1
    | 2, "b" -> 2
    | 3, _ -> 3
    | _ , "c" -> 4
    | _ -> 5;;

```

with your proposition, this is more verbose (I have to repeat coercion in each case):

```ocaml
let f = function
  | Empty -> 1
  | Node (1, ("a" : string <: t)) -> 1
  | Node (2, ("b" : string <: t)) -> 2
  | Node (3, _ )-> 3
  | Node (_ , ("c" : string <: t)) -> 4
  | _ -> 5

```

It will be more convenient if we could simply write:

```ocaml
let f = function
  | Empty -> 1
  | Node (1, "a") -> 1
  | Node (2, "b") -> 2
  | Node (3, _ )-> 3
  | Node (_ , "c") -> 4
  | _ -> 5

```

as with @Chris00 trick, but without defining a private type with a single unboxed variant.

---

<div class="post-metadata">

### Author: ![lpw25](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/lpw25/32/144_2.png) [@lpw25](https://discuss.ocaml.org/u/lpw25)
#### Post date: [February 19, 2018, 7:10pm UTC](https://discuss.ocaml.org/t/pattern-matching-on-private-strings/1581/17 "2018-02-19T19:10:20Z")

</div>

That would be implicit subtyping. The inference for implicit subtyping is tricky (to put it mildly) in general, and OCaml does not support it at this time.

---

<div class="post-metadata">

### Author: ![kantian](https://avatars.discourse-cdn.com/v4/letter/k/4bbf92/32.png) [@kantian](https://discuss.ocaml.org/u/kantian)
#### Post date: [February 20, 2018, 2:03pm UTC](https://discuss.ocaml.org/t/pattern-matching-on-private-strings/1581/18 "2018-02-20T14:03:58Z")

</div>

I don’t think we need implicit subtyping in all expressions, or even inference on subtyping (as in [MLsub](http://stedolan.net/research/mlsub.pdf) for example), but only when we pattern-match against a private type abbreviation (as in this topic).

Compare these two examples:

```ocaml
module M : sig
  type i = I of int 
  type t = private i
end = struct
  type i = I of int
  type t = i
end

module N : sig type t = private I of int end = struct type t = I of int end

```

In each case we define a type isomorphic to `int` (namely `I of int`) and one of its subtypes. But since, in the second case we do not “export” the `I` constructor we can directly pattern-match against a `t` value, and in the first one we have to coerce first.

```ocaml
let f (x : M.t) = match (x :> M.i) with M.I i -> i;;
val f : M.t -> int = <fun>

let g = function N.I i -> i;;
val g : N.t -> int = <fun>

```

and if we forget to coerce first, we have a type error:

```ocaml
let f (x : M.t) = match x with M.I i -> i;;
Error: This pattern matches values of type M.i
       but a pattern was expected which matches values of type M.t

```

Here, the compiler may implement the algorithm we use manually: it expects a pattern which matches a value of type `M.t`, but since `M.t` is a private type abbreviation it cannot be pattern matched directly, therefore it should be coerced first to its supertype `M.i`.

---

<div class="post-metadata">

### Author: ![lpw25](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/lpw25/32/144_2.png) [@lpw25](https://discuss.ocaml.org/u/lpw25)
#### Post date: [February 20, 2018, 2:52pm UTC](https://discuss.ocaml.org/t/pattern-matching-on-private-strings/1581/19 "2018-02-20T14:52:02Z")

</div>

> but since M.t is a private type abbreviation it cannot be pattern matched directly

Sure it can:

```ocaml
match (x : M.t) with
| y -> ...

```

So that leads to the question of how do you decide between

```ocaml
let foo (_ : M.t) = ()
let bar (_ : M.i) = ()

match (x : M.t) with
| y -> foo y

```

and

```ocaml
let foo (_ : M.t) = ()
let bar (_ : M.i) = ()

match (x : M.t) with
| y -> bar y

```

and that is before we are even inferring the type of the scrutinee. Consider:

```ocaml
let foo (_ : M.t) = ()

let f x =
  foo x;
  match x with
  | I y -> y + 1
  | _ -> 0

```

versus:

```ocaml
let foo (_ : M.t) = ()

let f x =
  match x with
  | I y -> foo x; y + 1
  | _ -> 0

```

Whatever way you look at it this is implicit subtyping. That doesn’t mean it’s impossible, but it does mean that it needs to be properly thought through and handled with care.

---

<div class="post-metadata">

### Author: ![c-cube](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/c-cube/32/1727_2.png) [@c-cube](https://discuss.ocaml.org/u/c-cube)
#### Post date: [February 20, 2018, 3:04pm UTC](https://discuss.ocaml.org/t/pattern-matching-on-private-strings/1581/20 "2018-02-20T15:04:58Z")

</div>

> [@lpw25](#):
>
> match (x : M.t) with  
> | y -\> …

This only works for a toplevel match, doesn’t it? But if you have a record, a field of which is of type M.t, you couldn’t write a nested pattern properly, could you?

edit: misread, I thought it was an upcast before the matching. So even in the toplevel case you can only bind, not deconstruct, which is a strange discrepancy between private aliases and private definitions (`type t = private { … }`) which allow destructuring.

[Next page](https://discuss.ocaml.org/t/pattern-matching-on-private-strings/1581.md?page=2)
