{"action":"closed","issue":{"url":"https://api.github.com/repos/Kotlin/kotlin-coroutines/issues/72","repository_url":"https://api.github.com/repos/Kotlin/kotlin-coroutines","labels_url":"https://api.github.com/repos/Kotlin/kotlin-coroutines/issues/72/labels{/name}","comments_url":"https://api.github.com/repos/Kotlin/kotlin-coroutines/issues/72/comments","events_url":"https://api.github.com/repos/Kotlin/kotlin-coroutines/issues/72/events","html_url":"https://github.com/Kotlin/kotlin-coroutines/issues/72","id":192701850,"number":72,"title":"Monadic do notation (requires continuations that can be called multiple times)","user":{"login":"h0tk3y","id":1888526,"avatar_url":"https://avatars1.githubusercontent.com/u/1888526?v=3","gravatar_id":"","url":"https://api.github.com/users/h0tk3y","html_url":"https://github.com/h0tk3y","followers_url":"https://api.github.com/users/h0tk3y/followers","following_url":"https://api.github.com/users/h0tk3y/following{/other_user}","gists_url":"https://api.github.com/users/h0tk3y/gists{/gist_id}","starred_url":"https://api.github.com/users/h0tk3y/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/h0tk3y/subscriptions","organizations_url":"https://api.github.com/users/h0tk3y/orgs","repos_url":"https://api.github.com/users/h0tk3y/repos","events_url":"https://api.github.com/users/h0tk3y/events{/privacy}","received_events_url":"https://api.github.com/users/h0tk3y/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":8,"created_at":"2016-11-30T22:43:35Z","updated_at":"2017-03-20T12:40:19Z","closed_at":"2017-03-20T12:40:19Z","body":"I'm trying to get close to the _Haskell do notation_ for [my monads implementation attempt](https://github.com/h0tk3y/kotlin-monads.git). \r\n\r\nIn Haskell, a _do_ block is translated into nested `>>=` calls, like this:\r\n\r\n    m = do\r\n        x <- [1, 2, 3]\r\n        y <- [x, x]\r\n        [y, y + 1]\r\n\r\n    // translated into:\r\n\r\n    m = [1, 2, 3] >>= x -> // f\r\n        [x, x] >>= y -> // g\r\n            [y, y+1]\r\n\r\nHere, `m` results into `[1, 2, 1, 2, 2, 3, 2, 3, 3, 4, 3, 4]`. Note that it's the `>>=` implementation that decides how to (and whether to) call `f` and `g`. In this example, `f` is called 3 times, and `g` is called twice each time.\r\n\r\nIn Kotlin, the coroutine transformation can be used to do almost the same: we can pass the `Continuation<T>` into the `bind` implementation, so that it calls the continuation.\r\n\r\n    val m = doWith(monadListOf(0)) {\r\n        val x = bind(monadListOf(1, 2, 3))\r\n        val y = bind(monadListOf(x, x))\r\n        then(monadListOf(y, y + 1))\r\n    } as MonadList\r\n\r\n    println(m) // MonadList(list=[1, 2, 1, 2, 2, 3, 2, 3, 3, 4, 3, 4])\r\n\r\nBut several problems arise:\r\n\r\n* A `Continuation<T>` implemented by a state machine modifies its `label`, so that we cannot run one continuation several times from the same `label`. _The workaround I used: back up the `label` through reflection before the `resume` call and restore it once the call returns._\r\n\r\n* If there are mutable variables declared inside the coroutine block, their state is naturally shared between the runs of the continuation. Example:\r\n\r\n        val m = doWith(monadListOf(0)) {\r\n            for (i in 1..10)\r\n                then(monadListOf(0, 0))\r\n        } as MonadList\r\n\r\n        println(m) // MonadList(list=[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])\r\n        // not 1024 items as one would expect, because of `i` shared between the runs\r\n\r\n     Neither prohibiting `var`s in such a coroutine nor defensive copying of the `var`s seems to solve the problem: a continuation can still use and mutate state from somewhere else."}}
{"actor":{"display_login":"elizarov"}}