-
Notifications
You must be signed in to change notification settings - Fork 326
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
Adding my comments to Intersection Types documentation #11838
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -42,17 +42,61 @@ Complex.from (that:Float) = Complex.Num that 0 | |
``` | ||
and uses them to create all the values the _intersection type_ represents. | ||
|
||
> [!NOTE] | ||
> Note that if a `Float.from (that:Complex)` conversion were available in the scope, | ||
> any `Complex` instance would be convertible to `Float` regardless of how it was constructed. | ||
> To ensure that such mix-ins are only available on values that opt-in to being | ||
> an intersection type (like in the `Complex` example above where we include | ||
> the `Float` mix-in only if `self.im == 0`), we need to ensure that the conversion | ||
> used to create the intersection type is not available in the default | ||
> conversion resolution scope. Thus it cannot be defined in the same module | ||
> as `Complex` or `Float` types, but instead it should be defined in a separate | ||
> module that is only imported in the place that will be constructing the multi-values. | ||
|
||
## Narrowing Type Check | ||
|
||
When an _intersection type_ value is being downcast to _one of the types it already represents_, | ||
such a check is: | ||
this type becomes its 'visible' type. Any additional types it represents become hidden. | ||
|
||
The following operations consider only the 'visible' part of the type: | ||
- recorded for purposes of [dynamic dispatch](../types/dynamic-dispatch.md) | ||
- recorded for cases when the value is passed as an argument | ||
- however the value still keeps (internal) knowledge of all the types it represents | ||
|
||
However the value still keeps (internal) knowledge of all the types it represents. | ||
|
||
Thus, after casting a value `cf:Complex&Float` to just `Complex`, e.g. `c = cf:Complex`: | ||
- method calls on `c` will only consider methods defined on `Complex`, | ||
- the value `c` can only be passed as argument to methods expecting `Complex` type, | ||
if a `Float` parameter is expected that will raise a type error. | ||
|
||
As such a _static analysis_ knows the type a value _has been cast to_ and | ||
can deduce the set of operations that can be performed with it. However, the value | ||
_can be cast to_ explicitly. | ||
can deduce the set of operations that can be performed with it. Moreover, any | ||
method calls will also only accept the value if it satisfies the type it | ||
_has been cast to_. Any additional remaining types that it had before the cast | ||
become hidden and can only be brought back through an _explicit_ cast. | ||
|
||
To perform an explicit cast that can uncover the 'hidden' part of a type, one can either: | ||
- write a type asserting expression - e.g. `f = c:Float`, | ||
- or inspect the types in a `case` expression, e.g. | ||
``` | ||
case c of | ||
f : Float -> f.sqrt | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does not work. Reported as |
||
_ -> "Not a float" | ||
``` | ||
|
||
> [!WARNING] | ||
> Keep in mind that while both argument type check in method definitions and a | ||
> 'type asserting' expression look similarly, they have slightly different behaviour. | ||
> ``` | ||
> f a:Float = a | ||
> g a = a:Float | ||
> ``` | ||
> These two functions, while very similar, will have different behaviour when | ||
> passed a value like the value `c` above. The function `f` will fail with | ||
> a type error, because the visible type of `c` is just `Complex` (assuming | ||
> the conversion to `Float` is not available in the current scope). | ||
> However, the function `g` will accept the same value and return it as | ||
> a `Float` value, based on the 'hidden' part of its type. | ||
Comment on lines
+87
to
+99
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I want to make it clear that while the syntax is very similar, the checked argument and type-asserting expressions are actually different and behave differently in regard to the 'hidden' types. |
||
|
||
> [!NOTE] | ||
> In the **object oriented terminology** we can think of | ||
|
@@ -75,7 +119,7 @@ _can be cast to_ explicitly. | |
> This behavior is often described as being **openness to subclasses**. E.g. the `c:Complex` | ||
> check allows values with _intersection types_ that include `Complex` to pass thru with | ||
> all their runtime information available, | ||
> but one has to perform an explicit cast to extract the other types associated with | ||
> but one has to perform an explicit cast (similar to `instanceof` check in Java) to extract the other types associated with | ||
> such a value. | ||
|
||
This behavior allows creation of values with types like `Table&Column` to represent a table | ||
|
@@ -88,7 +132,7 @@ Such a `Table&Column` value can be returned from the above `Table.join` function | |
having only `Table` behavior by default, still being able to be explicitly casted by the visual environment | ||
to `Column`. | ||
|
||
## Converting Type Check | ||
## Conversions | ||
|
||
When an _intersection type_ is being checked against a type it doesn't represent, | ||
any of its component types can be used for [conversion](../syntax/conversions.md). | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's correct and exactly as prototyped in the tests.