Skip to content

Commit fa8fa14

Browse files
committed
Updates after gaining experience with the prototype
1 parent d2b42b0 commit fa8fa14

3 files changed

Lines changed: 39 additions & 13 deletions

File tree

RationaleMCP/0034/ReadMe.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,16 @@ See [separate document](rationale.md).
3030
The introduction of the keyword `unknown` introduces a backwards incompatibility with code making use of that name for identifiers.
3131

3232
## Tool Implementation
33-
In progress.
33+
A prototype has been implemented in a development version of Wolfram SystemModeler. In the prototype, the type is named `__Wolfram_Ternary`, and the third truth value is named `__Wolfram_unknwon`.
3434

3535
### Experience with Prototype
36-
None yet.
36+
Although introducing a new built-in type is a change that ammounts to a large number of smaller changes, finding the places in a code base that need attention is easy due to the similarity between `Ternary` and `Boolean`. In a similar way, the implicit conversion from `Boolean` to `Ternary` is a feature that can be implemented by glancing at the handling of implicit conversion from `Integer` to `Real`.
37+
38+
Regarding the application of this MCP to a new attribute called `visible` in the `Dialog` annotation, the proposed choice Kleene logic certainly gets the job done. The default value of `unknown` which means _apply tool-specific rules for visibility_, a user can easily write a ternary logical expression to override the default in either way, and the expression may also evaluate to `unknown` in cases where the user don't want to fall back on the tool logic. Thanks to the implicit cast from `Boolean`, most uses of `visible` would probably be in the simple forms `visible = true` or `visible = false`. However, upon closer acquaintance with the Kleene logic, which still appears as the most natural choice for `Ternary`, it has been questioned whether this is the best way to model the absence of information, see [rationale](rationale.md#The-option-type-alternative).
3739

3840
## Required Patents
3941
To the best of our knowledge, there are no patents that would conflict with the incorporation of this MCP.
4042

4143
## References
44+
- Wikipedia, _Three-valued logic_, https://en.wikipedia.org/wiki/Three-valued_logic
45+
- Wikipedia, _Four-valued logic_, https://en.wikipedia.org/wiki/Four-valued_logic

RationaleMCP/0034/rationale.md

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -60,30 +60,48 @@ A completely different way of introducing ternary logic would be to introduce a
6060
```
6161
Ternary t = unknown;
6262
```
63-
one would then write something like
63+
one would then write something like one of the alternatives
6464
```
65-
Boolean? t = none;
65+
Boolean? t = Boolean?(); /* Explicit construction of the 'none' of a particular option type. */
6666
```
67-
where the `?` plays a similar role as an array dimension; it constructs a new type based on the type to the left. In this case, an option type, meaning that the value of `t` is either a `Boolean` value, or a value representing the absence of a `Boolean` value. To explicitly a known ternary value, one could have a construct like `some(true)` instead of `Ternary(true)`.
67+
or
68+
```
69+
Boolean? t = none; /* Using type inference to infer the particular option type. */
70+
```
71+
where the `?` plays a similar role as an array dimension; it constructs a new type based on the type to the left. In this case, an option type, meaning that the value of `t` is either a `Boolean` value, or a value representing the absence of a `Boolean` value.
72+
73+
While the type inference alternative with `none` looks more elegant on first glance, it doesn't really fit well with current Modelica, and there is also a problem with type inference and implicit conversion that speaks to the advantage of explicitly giving the type of a _none_-value. For the rest of this section, only the `Boolean?()` alternative for constructing the _none_-value is considered. Explicit construction of a non-_none_ value of `Boolean?` would take the form `Boolean?(e)` where `e` is an expression of type `Boolean`. There is thus an obvious way to define implicit conversion from any type `T` to `T?` simply by the mapping `t` → `T?(t)`, thus making the use of `Boolean?` almost as convenient as the use of `Ternary` (the difference being the keyword `unknown` vs the more cumbersome `Boolean?()`). (To see why implicit conversion doesn't work nicely with type inference, note that the implicit conversion from `none` to `Boolean??` is ambiguous; should it be `Boolean??()` or `Boolean??(Boolean?())`.)
6874

6975
Even though the use of option types could be restricted to `Boolean` to start with, it would open up for supporting more types in the future. Given the use case of allowing an expression of a built-in attribute to refer to the default value, it seems as if this could be useful for other types as well. For example, pretend that the `group` of `Dialog` didn't have `"Parameters"` as fixed start value, allowing tools to organize dialogs as they see fit. Then one could imagine giving an expression for `group` that only shall determine the group under certain circumstances, and otherwise leave it to the tool to decide. Then the use of a `String` option would be an elegant way of making this possible.
7076

77+
Another advantage of introducing option types instead of `Ternary` would be that it would probably be acceptable to say that no option type can be used for indexing into arrays. This would simplify parts of the implementation compared to `Ternary`.
78+
7179
However, these are some reasons for sticking with `Ternary` instead of `Boolean?`:
72-
- If the usual ternary logic is what we want — which is the assumption of this MCP — the use of `Boolean?` for would imply an unnatural interpretation of `none`. [This argument is elaborated below.](#Using-none-to-represent-undefined)
73-
- Introducing the literal `none` to refer to the absence of a value for an option type leads to a significant change of the Modelica type system, as `none` can have any option type. Explicitly writting out the type as in `none(Boolean)` would be too inconvenient compared to just saying `unknown`.
74-
- Implicit conversion from `Boolean` really simplifies use of ternary logic, but implicit conversion to `Boolean?` doesn't generalize to option types in general. (However, it works for non-option types, which might be good enough to justify it.)
80+
- If the usual ternary logic according to Kleene is what we want — which is the assumption of this MCP — the use of `Boolean?` for would imply an unnatural interpretation of `none`. [This argument is elaborated below.](#Using-none-to-represent-undefined)
81+
- Introducing the literal `none` to refer to the absence of a value for an option type leads to a significant change of the Modelica type system, as `none` can have any option type. Even if type inference would be implemented, there would be problems when it comes to implicit conversions (see above).
82+
- Explicitly writting out the type of a _none_ as in `Boolean?()` would be inconvenient compared to just saying `unknown`. (However, it would then be natural to define implicit conversion to any option type.)
7583
- Attributes of other type than `Boolean` typically have a default behavior that can be expressed with a default value (like the empty string in case of `String`), removing the need for an option type to express the absence of a value.
76-
- The `Boolean?` type might end up being the only special case of an option type with meanings given to the built-in operators.
84+
- The `Boolean?` type might end up being the only special case of an option type with meanings given to the built-in logical operators. (Possibilities to define meanings for other option types exist. For example, one could imagine the `Real?()` and `Integer?()` both being at the same time additive zeros and multiplicative ones. The question is whether there would ever be a need to introduce such definitions in the language.)
85+
- Relational operators would need to be defined generically, most likely giving the order `Boolean()?` < `Boolean(false)?` < `Boolean(true)?`, which doesn't correspond to the understanding of `Boolean?()` as some kind of middle ground between false and true.
7786
- Defining external language interface for option types is a pretty big change compared to just introducing one new scalar type (it would need to be defined generically, not just with `Boolean?` in mind).
7887
- It is probably a bad idea to just introduce option types in Modelica without considering the more general concepts that would give option types as a special case. Such more general constructs inspired by MetaModelica have been discussed at many design meetings without getting much traction.
7988

8089
## Using `none` to represent _undefined_
81-
While possible to interpret `none` as _unknown_ and define logical operation on `Boolean?` in the same way as for `Ternary`, the generalization of this interpretation to other option types such as `Real?` or `String?` isn't as useful. The natural interpretation of `none` would rather be _undefined_, which leads to more useful generalizations to other option types.
90+
While possible to interpret `none` as _unknown_ and define logical operation on `Boolean?` in the same way as for `Ternary` to get a Kleene logic, the generalization of this interpretation to other option types such as `Real?` or `String?` isn't as useful. The natural interpretation of `none` would rather be _undefined_, which leads to more useful generalizations to other option types.
91+
92+
For example, one could define that concatenation with an _undefined_ `String?`, would be a no-op, and the same for addition or multiplication with an _undefined_ `Real?`. For `Boolean?` it would then be natural to define both disjunction and conjunction with _undefined_ to be no-ops, leading to things such as `none and true = some(true)`.
93+
94+
Combined with `Ternary` to get `Ternary?`, one could define four-valued logic, having its own applications beyond both `Ternary` and `Boolean?`. In detail, by identifying `true` both with `Ternary(true)` and `Boolean?(true)`, and similarly for `false`, the truth tables for `Ternary` could be reordered and extended so that they define consistent tables for all of `Boolean`, `Ternary`, `Boolean?` and `Ternary?`. For instance, consider conjunction and let `neither` refer to `Boolean?()` for brevity:
8295

83-
For example, one could define that concatenation with an _undefined_ `String?`, would be a no-op, and the same for addition or multiplication with an _undefined_ `Real?`. For `Boolean?` it would then be natural to define both disjunction and conjunction with _undefined_ to be no-ops, leading to things such as `none and none = some(true)`.
96+
| `x and y` | `y = neither` | `y = false` | `y = true` | `y = unknown` |
97+
| ------------- | ------------- | ----------- | ------------- | ------------- |
98+
| `x = neither` | `neither` | `false` | `true` | `unknown` |
99+
| `x = false` | `false` | `false` | `false` | `false` |
100+
| `x = true` | `true` | `false` | `true` | `unknown` |
101+
| `x = unknown` | `unknown` | `false` | `unknown` | `unknown` |
84102

85-
Combined with `Ternary` to get `Ternary?`, one could define four-valued logic, having its own applications beyond both `Ternary` and `Boolean?`.
103+
Please note that this logical table does not correspond to the often cited four-valued logic by Belnap, hinting at the potential problems of reaching agreement on how to define logic on `Boolean?` and `Ternary?` in Modelica.
86104

87105
For the numeric types `Real` and `Integer`, a better analog to `unknown` would be `NaN` (not-a-number), having very different arithmetic behavior compared to the no-ops of _undefined_. For example, this gives the expected behavior of adding _unknown_ to any number resulting in _unknown_.
88106

89-
To summarize, while option types have many interesting applications — including modeling of built-in attributes with non-trivial defaults — it would be a mistake to use `Boolean?` for the usual ternary logic with _unknown_ as the third truth value. This also shows that `Ternary` is not going to become redundant if option types are added to Modelica in the future.
107+
To summarize, while option types have many interesting applications — including modeling of built-in attributes with non-trivial defaults — it would be a mistake to use `Boolean?` for the usual ternary logic according to Kleene with _unknown_ as the third truth value. This also shows that `Ternary` is not going to become redundant if option types are added to Modelica in the future.

RationaleMCP/0034/ternary.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ There is a total order of the possible `Ternary` values given by `Ternary(false)
3232

3333
## Expressions with Ternary
3434

35+
Logical operations on `Ternary` are defined according to Kleene, where `unknown` can be thought of as representinc uncertainty about being `true` or `false`. With this interpretation the Kleene logic tables then follow from the Boolean logic.
36+
37+
For example, to evaluate `false or unknown`, one has to consider both possible outcomes for the uncertain operand, meaning that the result might be ither `false or false` or `false or true`. Since the different outcomes don't agree, the result of the operation is uncertain, represented by `unknown`.
38+
3539
### Unary operators
3640
Unary operators on `Ternary`, where `x` is an expression of type `Ternary`:
3741

0 commit comments

Comments
 (0)