{"action":"created","issue":{"url":"https://api.github.com/repos/keean/zenscript/issues/27","repository_url":"https://api.github.com/repos/keean/zenscript","labels_url":"https://api.github.com/repos/keean/zenscript/issues/27/labels{/name}","comments_url":"https://api.github.com/repos/keean/zenscript/issues/27/comments","events_url":"https://api.github.com/repos/keean/zenscript/issues/27/events","html_url":"https://github.com/keean/zenscript/issues/27","id":181826538,"number":27,"title":"Typeclass objects","user":{"login":"shelby3","id":247731,"avatar_url":"https://avatars.githubusercontent.com/u/247731?v=3","gravatar_id":"","url":"https://api.github.com/users/shelby3","html_url":"https://github.com/shelby3","followers_url":"https://api.github.com/users/shelby3/followers","following_url":"https://api.github.com/users/shelby3/following{/other_user}","gists_url":"https://api.github.com/users/shelby3/gists{/gist_id}","starred_url":"https://api.github.com/users/shelby3/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shelby3/subscriptions","organizations_url":"https://api.github.com/users/shelby3/orgs","repos_url":"https://api.github.com/users/shelby3/repos","events_url":"https://api.github.com/users/shelby3/events{/privacy}","received_events_url":"https://api.github.com/users/shelby3/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":39,"created_at":"2016-10-08T13:35:41Z","updated_at":"2016-10-09T19:18:10Z","closed_at":null,"body":"Typeclass objects offer dynamic (i.e. run-time and open modularity<sup>1</sup>) polymorphism by binding the typeclass bound to the static (compile-time) type of the reference and tagging the data type instances that the reference can contain, so that the correct dictionary can be dispatched dynamically at run-time.\r\n\r\nThey are named \"[_trait objects_](https://doc.rust-lang.org/book/trait-objects.html)\" in Rust and \"[_existential quantification_](https://prime.haskell.org/wiki/ExistentialQuantification)\" (e.g. `forall a`) or \"[_existential typeclass_](https://lukepalmer.wordpress.com/2010/01/24/haskell-antipattern-existential-typeclass/)\" in Haskell.\r\n\r\n<sup>1</sup> Means we can't compile the universe, so we can't know all the data types required in dependency injection scenarios. Dynamic polymorphism is not just a run-time artifact, but it is also the fact of the real-world where [total orders can't exist](https://github.com/keean/zenscript/issues/22#issuecomment-250974865) (i.e. the Second Law of Thermodynamics, Halting Problem, Incompleteness Theorem, Russell's Paradox, [Byzantine Generals Problem](https://bitcointalk.org/index.php?topic=1183043.msg13819494#msg13819494), Byzantine [fault-tolerance with CAP theorem](https://bitcointalk.org/index.php?topic=1319681.msg13778110#msg13778110), impossibility of existence [without a quantified speed-of-light](https://github.com/keean/zenscript/issues/14#issuecomment-252026903), etc). As well, there are [no total orders of trustless, decentralization](https://bitcointalk.org/index.php?topic=1549494.0) either.\r\n\r\n### Expression Problem\r\n\r\nThey [have the benefit w.r.t. to Wadler's Expression Problem](https://github.com/keean/zenscript/issues/14#issue-179109775) of delaying the binding of interface to data on construction of the typeclass object as opposed to OOP subclassing (and Scheme/JavaScript prototype<sup>2</sup>) which binds the interface to all instances of the subclassed type (on instantiation of the data). So they solve the Expression Problem up the point of instantiation of the typeclass object, but beyond that point while they allow adding new data types (via the aforementioned dynamic dispatch) they don't allow extending new operations after the instantation of the typeclass object which binds the allowed typeclass interface(s). Typeclass objects enable heterogeneous collections with dynamic extension of the collection of data types without requiring an invariant collections data structure (i.e. they can be the element type of an array). Whereas, typeclass bounds on function definitions delay binding the interface until the function call site and thus solve the Expression Problem up to that point, but they don't enable heterogeneous collections with dynamic extension of the collection of data types except via unions. Unions can both enable heterogeneous collections with dynamic extension of the collection of data types and delay binding of the interface until the function call site, but they require an invariant collections data structure such as a list.\r\n\r\n<sup>2</sup> Note that prototype programming can add new operations (but forces all instances of a prototype to take those new interfaces) and add new data types, but it can't add different interfaces to instances of the same prototype. Whereas, type classing can differentiate.\r\n\r\n### Syntax and Pecularities\r\n\r\n@shelby3 [wrote](https://github.com/keean/zenscript/issues/11#issuecomment-252351006):\r\n> >> Well obviously that is useless and not what I was referring to. I mean for example, I have a collection of typeclass objects and I want to sort or find them, so I need a relation.\r\n> >\r\n> > A relation only applies to two objects of the same type.\r\n> \r\n> Exactly. So thus `Eq<A, A>` is useless for what I wrote above.\r\n> \r\n> > One answer is to provide a mapping from each object type to a partial order (or total order).\r\n> \r\n> So akin to subsumption to a subclass, except open to delayed definition. That might work for `sort`.\r\n> \r\n> Or another alternative is `Eq<A, B>` accepts any type `B`, but always returns `false` if `B` is not `A`. So `find` will work.\r\n> \r\n> Okay I see how maybe typeclass objects are still useful. Thanks.\r\n\r\n@shelby3 [wrote](https://github.com/keean/zenscript/issues/11#issuecomment-252365283):\r\n> @keean wrote:\r\n> > data Variant = for<A, B> Variant(A) requires A : Eq<B>\r\n> \r\n> `data Variant = Variant(A | Any) where A: Eq<Any>`\r\n\r\nThat seems to be a general solution and I like it very much, unless someone can point out flaws.\r\n\r\nSo typeclass objects are always conceptually with `| Any`, e.g.:\r\n\r\n```\r\nlet x: A where Show<A | Any> = MyType(1, 2)\r\nlet y: A where Eq<A | Any, Any> = MyType(1, 2)\r\n```\r\n\r\nOr in my (and Rust's) preferred OOPish style: \r\n\r\n```\r\nlet x: A where (A | Any): Show = MyType(1, 2)\r\nlet y: A where (A | Any): Eq<Any> = MyType(1, 2)\r\n```\r\n\r\nBut I prefer we can write that shorthand (and so we only need `where` clauses on function types and definitions):\r\n\r\n```\r\nlet x: Show = MyType(1, 2)\r\nlet y: Eq<Any> = MyType(1, 2)\r\n```\r\n\r\nHope you are also starting to see another reason why I favored an OOPish style because it is also more consistent with typeclass objects (and I actually did intuitively anticipate/expect this but not with complete solution worked out).\r\n\r\nP.S. my understanding is that any function defined for a typeclass bound would also accept typeclass objects with that bound. The compiler would create a dynamic dispatch version of the said function on demand to be used when ever a reference to it is passed around. Seems to me that only functions called nominally can be monomorphized."},"comment":{"url":"https://api.github.com/repos/keean/zenscript/issues/comments/252506286","html_url":"https://github.com/keean/zenscript/issues/27#issuecomment-252506286","issue_url":"https://api.github.com/repos/keean/zenscript/issues/27","id":252506286,"user":{"login":"shelby3","id":247731,"avatar_url":"https://avatars.githubusercontent.com/u/247731?v=3","gravatar_id":"","url":"https://api.github.com/users/shelby3","html_url":"https://github.com/shelby3","followers_url":"https://api.github.com/users/shelby3/followers","following_url":"https://api.github.com/users/shelby3/following{/other_user}","gists_url":"https://api.github.com/users/shelby3/gists{/gist_id}","starred_url":"https://api.github.com/users/shelby3/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shelby3/subscriptions","organizations_url":"https://api.github.com/users/shelby3/orgs","repos_url":"https://api.github.com/users/shelby3/repos","events_url":"https://api.github.com/users/shelby3/events{/privacy}","received_events_url":"https://api.github.com/users/shelby3/received_events","type":"User","site_admin":false},"created_at":"2016-10-09T19:18:10Z","updated_at":"2016-10-09T19:18:10Z","body":"@keean wrote:\r\n>> OTOH, first-class without wrapping makes inference undecidable.\r\n>\r\n> It has nothing to do with inference as you have to provide the type signature in either case\r\n\r\nWell yeah that is my point! But your cited paper [claims otherwise](http://web.cecs.pdx.edu/~mpj/pubs/popl97-fcp.pdf#page=12):\r\n\r\n> We have described a modest extension of the HindleyMilner type system that offers both the convenience of type inference and the expressiveness of first-class polymorphism"}}
{"actor":{"display_login":"shelby3"}}