{"action":"opened","issue":{"url":"https://api.github.com/repos/ceylon/ceylon-js/issues/561","labels_url":"https://api.github.com/repos/ceylon/ceylon-js/issues/561/labels{/name}","comments_url":"https://api.github.com/repos/ceylon/ceylon-js/issues/561/comments","events_url":"https://api.github.com/repos/ceylon/ceylon-js/issues/561/events","html_url":"https://github.com/ceylon/ceylon-js/issues/561","id":78837670,"number":561,"title":"support type lambdas that capture generic arguments","user":{"login":"jvasileff","id":236050,"avatar_url":"https://avatars.githubusercontent.com/u/236050?v=3","gravatar_id":"","url":"https://api.github.com/users/jvasileff","html_url":"https://github.com/jvasileff","followers_url":"https://api.github.com/users/jvasileff/followers","following_url":"https://api.github.com/users/jvasileff/following{/other_user}","gists_url":"https://api.github.com/users/jvasileff/gists{/gist_id}","starred_url":"https://api.github.com/users/jvasileff/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jvasileff/subscriptions","organizations_url":"https://api.github.com/users/jvasileff/orgs","repos_url":"https://api.github.com/users/jvasileff/repos","events_url":"https://api.github.com/users/jvasileff/events{/privacy}","received_events_url":"https://api.github.com/users/jvasileff/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":0,"created_at":"2015-05-21T05:23:25Z","updated_at":"2015-05-21T05:23:25Z","closed_at":null,"body":"In the code below, `Functor` has a generic parameter `Container` that takes type constructors of the form `Container<Element>`. This works well for types like `Singleton`, `List`, and `Set`.\r\n\r\n`Pair` is a class with two generic parameters (`Pair<A,B>`) - one more of course than `Container`.\r\n\r\nIn order to satisfy `Container` with `Pair`, a type lambda is necessary to resolve this difference. `PairLambda` performs this task, capturing `PairFunctor`'s `A` for `Pair`'s first type parameter, and designating `Pair`'s second type parameter as `Container`'s `Element`.\r\n\r\nThis type checked code:\r\n\r\n```ceylon\r\nclass Pair<A,B>() {}\r\n\r\ninterface Functor<Element, Container> \r\n        given Container<Element> {\r\n\r\n    shared default void doSomething() {\r\n        print(`Element`);\r\n    }\r\n}\r\n\r\nclass PairFunctor<A, B>() \r\n        satisfies Functor<B, PairLambda>\r\n        given A satisfies Object {\r\n\r\n    shared alias PairLambda<E> => Pair<A,E>;\r\n}\r\n\r\nvoid callDoSomething<Element, Container>\r\n        (Functor<Element, Container> functor)\r\n        given Container<Element> {\r\n\r\n    functor.doSomething();\r\n}\r\n\r\nshared void testPairFunctor() {\r\n    value functor = PairFunctor<Integer,Float>();\r\n    functor.doSomething();\r\n    callDoSomething(functor);\r\n}\r\n```\r\n\r\nresults in:\r\n\r\n```\r\nceylon.language::Float\r\nsnapjs.base-0.0.1.js:5370\r\n$16l1={t:Pair,a:{B$Pair:'E$PairLambda',A$Pair:pairFunctor$.$$targs$$.A$PairFun\r\n                                                                    ^\r\nTypeError: Cannot read property 'A$PairFunctor' of undefined\r\n    at pairFunctor$.PairLambda$PairFunctor (snapjs.base-0.0.1.js:5370:138)\r\n    at testPairFunctor (snapjs.base-0.0.1.js:5385:75)\r\n    at [eval]:1:366\r\n```\r\n\r\nIf `PairLambda` is rewritten to not capture `PairFunctor.A`, the program works. With:\r\n\r\n```ceylon\r\n    shared alias PairLambda<E> => Pair<String,E>;\r\n```\r\nyou get:\r\n```\r\nceylon.language::Float\r\nceylon.language::Float\r\n```"}}