You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: RationaleMCP/0034/ReadMe.md
+6-2Lines changed: 6 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -30,12 +30,16 @@ See [separate document](rationale.md).
30
30
The introduction of the keyword `unknown` introduces a backwards incompatibility with code making use of that name for identifiers.
31
31
32
32
## 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`.
34
34
35
35
### 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).
37
39
38
40
## Required Patents
39
41
To the best of our knowledge, there are no patents that would conflict with the incorporation of this MCP.
Copy file name to clipboardExpand all lines: RationaleMCP/0034/rationale.md
+29-11Lines changed: 29 additions & 11 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -60,30 +60,48 @@ A completely different way of introducing ternary logic would be to introduce a
60
60
```
61
61
Ternary t = unknown;
62
62
```
63
-
one would then write something like
63
+
one would then write something like one of the alternatives
64
64
```
65
-
Boolean? t = none;
65
+
Boolean? t = Boolean?(); /* Explicit construction of the 'none' of a particular option type. */
66
66
```
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?())`.)
68
74
69
75
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.
70
76
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
+
71
79
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.)
75
83
- 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.
77
86
- 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).
78
87
- 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.
79
88
80
89
## 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:
82
95
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)`.
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.
86
104
87
105
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_.
88
106
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.
Copy file name to clipboardExpand all lines: RationaleMCP/0034/ternary.md
+4Lines changed: 4 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -32,6 +32,10 @@ There is a total order of the possible `Ternary` values given by `Ternary(false)
32
32
33
33
## Expressions with Ternary
34
34
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
+
35
39
### Unary operators
36
40
Unary operators on `Ternary`, where `x` is an expression of type `Ternary`:
0 commit comments