-
Notifications
You must be signed in to change notification settings - Fork 7
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
Higher-kinds #10
Comments
It appears we can emit TypeScript code to implement
Since P.S. 9 lines of ZenScript becomes 19 lines of TypeScript and 29 lines of JavaScript not including code to set up the |
I don't think that is quite right. Monoid takes a parameter in no-object systems because is declaring free functions not methods:
The above is how I would want to do it in a no-objects system. The following is for an object system:
|
There is a further small problem with the above, identity is effectively a constructor function, so the second example is not quite right. Infact we would have to introduce a new keyword to make |
@keean wrote:
Your |
You are right, my implementation is wrong, but the type signature is correct, I was too quick cut-and-pasting from the posted code:
|
@keean wrote:
Yours is apparently the category theory correct Monoid and mine wasn't, but I don't see how you can implement the Edit: seems the most efficient way to sort a list is to convert it to an array, sort, then convert it back to list. So how to do that generically? Seems the only way is to have typeclass interface which converts to and from an array. Perhaps it is instructive that category theory doesn't help us, except maybe to warn of us to not try to do it with the incorrect Monoid example I showed. |
@keean wrote:
I showed how to do it in TypeScript using only type parameters. Perhaps you mean without the unsound runtime exceptions I had to use? |
To efficiently sort a list, try a merge-sort. Recursively split the list into two (can be done with references to the source list without changing it). When you get to single items take each item and put into a separate list. Then perform a merge operation on each pair of lists, repeatedly until only one list remains which will be sorted. The merge operation uses three lists, two input and one output. whilst there is an element in both source lists, it takes the lowest head of the two (or highest depending on desired order) and pushes it into the output list removing it from the input list. This repeats until one or both input lists are empty. If both are empty the merge is finished, otherwise we push the remaining items into the output removing them from the input, as they will already be in order. |
Trade-off of prematurely specializing the algorithm? |
Cross-referencing …
|
We must support HKT. |
Kinds are the type of type constructors. Thus higher-kinds are constructors on type constructors.
Some prior discussion at the Rust forum about higher-kinds may provide a clearer understanding of what they are and use cases.
It is important to note that the supertype of a union contains more types than its subtype, e.g.
Number|String
is the supertype ofNumber
. Thus we can not subsume to the greatest lower bound (aka GLB or common supertype) of the element type of an instance of anArray
, e.g. fromNumber
toNumber|String
, because some preexisting reference of typeArray<Number>
would access a data structure that contains alsoString
elements. Thus such a subsumption will not type check. Thus we are unable to add or insert elements (into an instance ofArray
) which have a type that is not already the subtype of the preexisting element type. Thus employingArray
with unions is not a solution to the Expression Problem, because we can't add new variants (types). Tangentially note that subsuming to the superclass for subclassing or typeclass objects (trait
in Rust) works fine withArray
, because the dynamic dispatch insures that no preexisting references to theArray
instance are invalidated by inserting or adding elements with new subtypes to the data structure, and thus it type checks. But subclassing and typeclass objects do not (or not entirely for typeclass objects) solve the Expression Problem, because new operations can't be added (for subclassing can't be added after instantiation of the class and for typeclass objects can't be added after instantiation of the typeclass object).But a
List
doesn't have this problem and is an invariant data structure, because thehead
of theCons
can be any type (if we are subsuming to a new union type) and any preexisting references to any element in the tail of the list will never access the new head, because aList
is a singly-linked data structure with new elements prepended. Thus lists allow adding new variants (types) even for union types (not just for subclassing and typeclass objects) and since this retains the explicit union type instead of otherwise premature subsumption to a dynamic dispatch (that is employed by subclassing and typeclass objects), then we can also add new operations as a delayed binding to any future typeclass bound (having the compiler automatically generate type-case logic for the dispatch at the trait bound call site). This was my invention as a solution to the Expression Problem.When I started thinking about how a
List
would interact with the first-class unions we accepted into ZenScript's design, I realized that if typeclasses can't provide a factory to construct a new instance of the data structure they are operating on, then it is impossible to write some generic operations such as a sort when employing subsuming heterogeneous unions with higher-order containers.For example, a
sort
operation needs to re-order the elements of a collection which is impossible to do insitu unless all elements of the collection have the same type, which entirely defeats the goal of adding new variants (types) to the collection to solve the Expression Problem. Thus the only way to sort theList
in general, is to make a new instance of aList
and sort into this newList
with the GLB element type. @keean suggested workarounds by passing in the factory for the value type separately. This was also mentioned by myself in another thread.But without higher-kinds or at least Rust's
Self
type (which afaik is a feature that can also be obtained with higher-kinds), then I don't see how a typeclass could declare a factory method? Because the return type of the factory method needs to be the type of implementing type of typeclass, yet the Monoid needs also to know the element type, so that is a type of type constructor higher-kind pattern. This is similar to an issue we were discussing at the Rust forum about how to write the method for iterator factory in a typeclass. Note thesort
operation needs to be able to return the same types as it input.Afaik, the generalized category theory compliant interface for a factory and append operation is the
Monoid
typeclass. Theidentity
method returns an empty new instance and theappend
adds new elements to the collection.The text was updated successfully, but these errors were encountered: