I was trying to have a coq notation for a shorter way to express a `list (option nat)`

. Something like:

`[[ 1, N, 2, 3, N, 4]]`

leading to `[Some 1, None, Some 2, Some 3, None, Some 4]`

where we just got to mention the numbers for it to be expanded to `Some`

values, yet there is a way to express `None`

values as well.

Is such a thing possible?

Can custom entries be of help here if it is possible to have a custom entry within a custom entry or something?

Like a notation for an outer custom entry like `[[ ... ]]`

and then an inner notation that can expand the `nat`

values to `option nat`

values?

```
Module OListNotations.
Notation "[[ ]]" := (@nil (option nat)) (format "[[ ]]") : olist_scope.
Notation "[[ x ]]" := (@cons (option nat) x nil) : olist_scope.
Notation "[[ x , y , .. , z ]]" := (@cons (option nat) x (@cons (option nat) y .. (@cons (option nat) z nil) ..)) : olist_scope.
Notation N := (@None nat).
Coercion Some_nat := (@Some nat).
Open Scope olist_scope.
End OListNotations.
Import OListNotations.
Compute [[ 1, N, 2, 3, N, 4]].
```

Two central tricks: First, I added the coercion `Some_nat`

so no notation for Some is needed. Second, I adapted the notations for lists from `Coq.Lists.List.ListNotations`

to only apply to `option nat`

- without that, the coercion from the first would not be triggered, because `[[4]]`

is interpreted as `list nat`

. Putting everything in a module and using a scope is good practice, but not necessary to make the example work.

Cool! Didn't know much about coercions in Coq. Read the docs and got some idea.

Thanks a lot!

Also thanks for telling about the use of modules to have better organized code. That's something I need to start using.

The `Some_nat`

coercion allows values of `nat`

to be made into `Some`

values of `option nat`

, right?

After having that coercion declared, I tried

```
Notation N := (@None nat).
Coercion Some_nat := (@Some nat).
Require Import List.
Import ListNotations.
Definition foo : list (option nat) := [ 1; N; 2; 3; N; 4].
(*
The term "[4]" has type "list nat" while it is expected to have type
"list (option nat)".
*)
```

but that didn't work.

So I guess the effect of the coercion is somehow limited to `[[ ... ]]`

. How is it so?

As @Yannick Forster was saying, the `[[`

notation uses `@cons (option nat)`

to force Coq to construct a list of `option nat`

You're writing a return type annotation, but that information is not propagated to the right spot... I wonder if `Program Definition`

would fix that (thanks to its different type inference algorithm), tho Program also changes a few other things.

bidi hints work

Oh, I didn't know that! Here's the elaborated example of what Gaëtan probably had in mind:

```
Require Import List.
Import ListNotations.
Arguments cons _ & _ _.
Coercion Some_nat := (@Some nat).
Compute [ 1; None; 2; 3; None; 4] : list (option nat).
```

Is there a way to generalise over the type in `option T`

? Not just for a specific type as with `nat`

?

Something like `Coercion Some_t := forall t:Type, @Some t`

?

Is that possible?

I would be surprised it were possible: with such a generic coercion, you would have two coercion paths from `A`

to `option (option A)`

(depending whether the second coercion happens inside or outside) so Coq wouldn't know which it should apply

Okay, I guess that's the limit then. Thanks everyone!

polymorphic coercions do exist, fwiw, but have restrictions. For instance, a coercion from option t to list t should work fine

t -> list t is probably impossible, but I don't understand @Kenji Maillard's reasoning: the only coercion is Some_t (Some_t n) it seems, but I don't know what would be the class of the generic t... Can one write a coercion *from* Sortclass? I guess not

AFAIK `Sortclass`

and `Funclass`

exist because in some situations you only know that something has to be a type/function but not more (ie the complete type something is checked against), so it makes sense to have those only as target classes but not sources

Yeah that's what I feared

Last updated: Feb 09 2023 at 00:03 UTC