{"action":"created","comment":{"url":"https://api.github.com/repos/tweag/ghc-proposals/pulls/comments/149371246","pull_request_review_id":74751911,"id":149371246,"diff_hunk":"@@ -0,0 +1,861 @@\n+.. proposal-number:: Leave blank. This will be filled in when the proposal is\n+                     accepted.\n+\n+.. trac-ticket:: Leave blank. This will eventually be filled with the Trac\n+                 ticket number which will track the progress of the\n+                 implementation of the feature.\n+\n+.. implemented:: Leave blank. This will be filled in with the first GHC version which\n+                 implements the described feature.\n+\n+.. highlight:: haskell\n+\n+This proposal is `discussed at this pull request <https://github.com/ghc-proposals/ghc-proposals/pull/0>`_. **After creating the pull request, edit this file again, update the number in the link, and delete this bold sentence.**\n+\n+.. contents::\n+\n+Linear Types\n+============\n+\n+This proposal introduces a notion of *linear function* to GHC. Linear\n+functions are regular functions that guarantee that they will use\n+their argument exactly once. Whether a function ``f`` is linear or not\n+is called the *multiplicity* of ``f``. We propose a new language\n+extension, ``-XLinearTypes``. When turned on, the user can enforce\n+a given multiplicity for ``f`` using a type annotation.\n+\n+The theory behind this proposal has been fully developed in a peer\n+reviewed conference publication that will be presented at POPL'18. See\n+the `extended version of the paper\n+<https://arxiv.org/abs/1710.09756>`_.\n+\n+Motivation\n+----------\n+\n+Haskell, along with a few other languages, heralded the notion of\n+*type safety* into mainstream programming. That is, *well-typed\n+programs do not go wrong*. Well-typed programs do sometimes crash, or\n+fail to terminate, but they do not segfault. Now, the system resources\n+that these programs manipulate have changing states, need to be\n+initialized before use and conversely, must be freed in a timely\n+manner. We want not just type safety in Haskell, but also *resource\n+safety*. We want well-typed programs that do not go wrong in the sense\n+that they might still crash, but they do not rewind the state of I/O\n+resources, these resources are never used before they are initialized,\n+are guaranteed to be freed by the time control flow exits user defined\n+scopes, and never used after being freed.\n+\n+This proposal hits another goal as a side benefit. In Haskell, impure\n+computations are typically structured as a sequence of steps, be it in\n+the ``IO`` monad or in ``ST``. The latter in particular serves to\n+precisely control which effects are possible and the scope within\n+which they are visible. But using monads to write \"locally impure\"\n+computations that still look pure from the outside has an unfortunate\n+consequence: computations are oversequentialized, making it hard for\n+the compiler to recover lost opportunities for parallelism.\n+\n+Linear types enable better solutions to both problems:\n+\n+1. using types to guarantee resource safety, and\n+2. using types to control the scope of effects without forcing an\n+   unnatural sequencing of mutually independent effects.\n+\n+The following example illustrates both points. Using linear types, we\n+express a pure API for mutable array construction (the type ``a ->. b``\n+is the type of linear functions, ``Unrestricted`` is such that\n+``Unrestricted a ->. b`` is isomorphic to ``a -> b``):\n+\n+::\n+\n+  data MArray a\n+  data Array a\n+  newMArray :: Int -> (MArray a ->. Unrestricted b) ->. Unrestricted b\n+  write :: MArray a ->. (Int, a) -> MArray a\n+  read :: MArray a ->. Int -> (MArray a, Unrestricted a)\n+  freeze :: MArray a ->. Unrestricted (Array a)\n+\n+The types in this interface ensure that values of type ``MArray a``\n+are always *unique* references to a mutable array. As a consequence,\n+mutations cannot be observed by the context, because references\n+aliasing each other is ruled out. Referencial transparency is\n+preserved.\n+\n+The two main benefits of this API are:\n+\n+- reads and writes on distinct arrays are not sequenced. This means\n+  that the compiler is free to reorder them, e.g. as an optimisation.\n+  We could go further and introduce `fork-join parallelism\n+  <https://en.wikipedia.org/wiki/Fork%E2%80%93join_model>`_ primitives\n+  where disjoint slices can be mutated in parallel, *e.g.* by\n+  different cores.\n+- The ``freeze`` function consumes the unique ``MArray`` by turning it\n+  into a non-unique immutable array. ``freeze`` does not, in fact,\n+  copy the array, it just changes its (static!) state. In the ``ST``\n+  implementation of ``MArray``, the primitive is ``unsafeFreeze``\n+  because it is up to the programmer to promise that they won't ever\n+  mutate the frozen ``MArray`` again. This shrinks the trusted code\n+  base. Or to put it another way: the user can now write more\n+  efficient code even when keeping to safe primitives only.\n+\n+We argue that linear types have far ranging consequences for the\n+language. Systems programming with quasi real-time requirements can\n+often benefit from easing pressure on the GC by taking long-lived\n+objects out of the GC-managed heap entirely. Fewer long-lived objects\n+in the heap means faster major collection times, hence shorter GC\n+pauses. Linear types enable *safe* manual memory management for\n+long-lived objects.\n+\n+With linear types, we can write an interface to ``malloc`` and\n+``free`` as follows:\n+\n+::\n+\n+  malloc :: Storable a => a ->. (Ptr a ->. Unrestricted b) ->. Unrestricted b\n+  read :: Storable a => Ptr a ->. (Ptr a, a)\n+  free :: a ->. ()\n+\n+This interface is safe in the sense that users of this interface get\n+two strong static guarantees:\n+\n+1. that all that they allocate will eventually be freed, and\n+2. that after freeing the associated pointer can never be read.\n+\n+With these two guarantees in hand, users no longer need to rely on the\n+GC for managing all resources, hence benefiting from lower tail\n+latencies and potentially higher throughput, while still getting\n+freedom from segfaults.\n+\n+Linear types don't just enable using Haskell for more use cases\n+(low-latency trading appliances, low-level services in\n+high-performance scientific computing clusters, etc). Correctly\n+tracking the lifecycle of I/O resources has been a vexing issue for\n+many network services. Creating a variant of the BSD socket API that\n+statically guarantees ordering constraints between API calls becomes\n+possible without the overhead of heavyweight encodings based *e.g.* on\n+parameterized monads.\n+\n+::\n+\n+  -- We need an variant of the IO monad where actions are linear\n+  data IOL a\n+  returnL :: a ->. IOL a\n+  bindL :: IOL a ->. (a ->. IOL b) ->. IOL b\n+\n+  -- Definition of sockets\n+  data State = Unbound | Bound | Listening | Connected\n+  data Socket (s :: State)\n+  data SocketAddress\n+\n+  -- When a (TCP) socket is created it is Unbound.\n+  socket :: IOL (Socket Unbound)\n+  -- To bind a socket to a port we take an Unbound socket, and make it\n+  -- Bound. The type of bindL will ensure that the socket is threaded\n+  -- through the computation, so that the (Socket Unbound) is not\n+  -- accessible: we cannot bind a socket twice.\n+  bind :: Socket Unbound ->. SocketAddress -> IOL (Socket Bound)\n+  -- A socket must be bound to a port before we start listening\n+  listen :: Socket Bound->. IOL (Socket Listening)\n+  -- A socket can accept multiple connection, therefore, the socket is\n+  -- returned in the same state by accept. A second, bidirectional,\n+  -- socket representing the connection is also returned. Both have to\n+  -- be used in a single-threaded fashion.\n+  accept :: Socket Listening ->. IOL (Socket Listening, Socket Connected)\n+  connect :: Socket Unbound ->. SocketAddress -> IOL (Socket Connected)\n+  send :: Socket Connected ->. ByteString -> IOL (Socket Connected, Unrestricted Int)\n+  receive :: Socket Connected -> IOL (Socket Connected, Unrestricted ByteString)\n+  close :: ∀s. Socket s -> IOL ()\n+\n+The `paper <https://arxiv.org/abs/1710.09756>`_ mentions other use\n+cases as well, such as efficient and safe data serialization as well\n+as using types to statically enforce interaction protocols between\n+communicating processes (*e.g.* via RPC calls). GHC users will no\n+doubt invent many more use cases over time.\n+\n+Proposed Change Specification\n+-----------------------------\n+\n+We introduce a new language extension. Types with a linearity\n+specification are syntactically legal anywhere in a module if and only\n+if ``-XLinearTypes`` is turned on.\n+\n+Definition\n+~~~~~~~~~~\n+\n+We say that a function ``f`` is *linear* when ``f u`` is consumed\n+exactly once implies that ``u`` is *consumed exactly once* (defined\n+as follows).\n+\n+- Consuming a value of a data type exactly once means evaluating it to\n+  head normal form, then consuming its fields exactly once\n+- Consuming a function exactly once means applying it and consuming\n+  its result exactly once\n+\n+The type of linear function from type ``A`` to type ``B`` is written\n+``A ->. B`` (see syntax below).\n+\n+Linearity is a strengthening of the contract of the regular function\n+type ``A -> B``, which will be called the type of *unrestricted*\n+functions.\n+\n+Remark: linear function ``f`` can diverge or be called on diverging\n+data. It may feel weird because ``f`` will not necessarily consume its\n+argument. But it's alright: the metatheory still works. One can think\n+of a diverging computation as not consuming its result exactly once,\n+therefore, it is vacuously true that if ``f u`` is consumed exactly\n+once, then ``u`` is consumed exactly once.\n+\n+Polymorphism\n+~~~~~~~~~~~~\n+\n+In order for linear functions and unrestricted functions not to live\n+in completely distinct worlds, to avoid code duplication, we\n+introduce a notion of polymorphism, dubbed *multiplicity polymorphism*,\n+over whether a function is linear.\n+\n+A linear function is said to have multiplicity ``1`` while an\n+unrestricted function is said to have multiplicity ``ω``. Multiplicity\n+polymorphic functions may have variable multiplicity, *e.g.*\n+\n+::\n+\n+  map :: (a :p-> b) -> [a] :p-> [b]\n+\n+without polymorphism we would need two implementations of `map`. With\n+the exact same code: one for ``p=1`` and one for ``p=ω``. Function\n+composition is even worse: it takes two multiplicity parameters, hence,\n+would require four identical implementations:\n+\n+::\n+\n+  (.) :: (b :p-> c) -> (a :q-> b) -> a :(p ':* q)-> c\n+\n+Syntax\n+~~~~~~\n+\n+The new primary constructs are: multiplicities and the multiplicity\n+indexed arrow.\n+\n+- Multiplicities are a datatype:\n+\n+  ::\n+\n+    data Multiplicity\n+      = Zero\n+      | One\n+      | Omega\n+      | Multiplicity :* Multiplicity\n+      | Multiplicity :+ Multiplicity\n+\n+  In the following, for conciseness, we write ``0`` for ``Zero``,\n+  ``1`` for ``One`` and ``U`` (ASCII) or ``ω`` (Unicode) for\n+  ``Omega``. See the Formalism section below for the significance of\n+  ``0``. Note: unification of multiplicities will be performed up to\n+  the semiring laws.\n+- The multiplicity annotated arrow, for polymorphism, is written\n+  ``a :p-> b`` (where ``a`` and ``b`` are types and ``p`` is a\n+  multiplicity). To avoid introducing a new notion of \"mixfix\"\n+  operators, we introduce a familly of (infix) type constructors:\n+  ``(:p->)`` for each multiplicity ``p``. This technically steals\n+  syntax as ``(:)`` is a valid type operator under the discouraged\n+  ``-XDataKinds`` syntax. But this should not be a problem in\n+  practice.\n+\n+The linear and unrestricted arrows are aliases:\n+\n+- ``(->)`` is an alias for ``(:'U ->)``\n+- ``(->.)`` (ASCII syntax) and ``(⊸)`` (Unicode syntax) are aliases\n+  for ``(:'1 ->)``\n+\n+Constructors & pattern-matching\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+Constructors of data types defined with the Haskell'98 syntax\n+\n+::\n+\n+  data Foo\n+    = Bar A B\n+    | Baz C\n+\n+have linear function types, that is ``Bar :: A ->. B ->. Foo``. This\n+is true in every module, including those without ``-XLinearTypes``\n+turned on. This implies that most types in ``base`` (``Maybe``,\n+``[]``, etc…) have linear constructors. We also make primivitive\n+tuples ``(,)`` have linear constructors.\n+\n+With the GADT syntax, multiplicity of the arrows is honored:\n+\n+::\n+\n+  data Foo2 where\n+    Bar2 :: A ->. B -> C\n+\n+then ``Bar2 :: A ->. B -> C``\n+\n+The definition of consuming a value in a data type exactly once must\n+be refined to take the multiplicities of fields into account:\n+\n+- Consuming a value in a datatype exactly once means evaluating it to\n+  head normal form and consuming its *linear* fields exactly once\n+\n+When pattern macthing a linear argument, linear fields are introduced\n+as linear variables, and unrestricted fields as unrestricted\n+variables:\n+\n+::\n+\n+  f :: Foo2 ->. A\n+  f (Bar2 x y) = x  -- y is unrestricted, hence does not need to be consumed\n+\n+An exception to this rule is ``newtype`` declarations in GADT syntax:\n+``newtype``-s must have only linear arguments (see Interactions\n+below). For backward compatibility, we propose, to make unrestricted arrow\n+``(->)`` in ``newtype``-s be interpreted as linear arrows, and create\n+a new warning ``unrestricted-newtype`` triggered when this happens.\n+\n+Base\n+~~~~\n+\n+Because linear functions only strengthen the contract of unrestricted\n+functions, a number of functions of ``base`` can get a more precise\n+type. However, for pedagogical reason, to prevent linear types from\n+interfering with newcomers' understanding the ``Prelude``, this\n+proposal does not modify ``base``. Instead we will release a library\n+exposing the stronger types for ``base`` functions. This library will\n+not redefine any type, and instead takes advantage of the fact that\n+data types, in ``base`` are linear by default to reuse the same types,\n+hence remain compatible with base.\n+\n+The only function which will need to change is ``($)`` because its\n+typing rule is built in the type checker. Ignoring the details about\n+levity and higher-rank polymorphism in the typing rule, the type\n+``($)`` will be:\n+\n+::\n+\n+  ($) :: (a :p-> b) ⊸ a :p-> b\n+\n+The precise content of the library is out of scope of this proposal,\n+but it will also contain convenient types to work with linear types\n+such as:\n+\n+::\n+\n+   data Unrestricted a where\n+     Unrestricted :: a -> Unrestricted a\n+\n+At any rate, any library changes are out-of-scope for this proposal.\n+Indeed, users are free to define their own alternative linear types\n+enabled variant of the `Prelude` and even the rest of `base`. To the\n+extent that these alternative preludes just reexport data type\n+definitions while changing only the types of functions, these preludes\n+will not contribute to splintering the ecosystem any more than the\n+myriad existing alternative preludes do.\n+\n+Formalism\n+~~~~~~~~~\n+\n+So far, we have considered only two multiplicities ``1`` and\n+``ω``. But the metatheory works with any so-called\n+sup-semi-lattice-ordered semi-ring of multiplicities. That is: there\n+is a 0, a 1, a sum and a product with the usual distributivity laws, a\n+(computable) order compatible with the sum and product, such that each\n+pair of multiplicities has a (computable) join. Even if there is only\n+three multiplicities in this proposal, the proposal is structured to\n+allow future extensions.\n+\n+Non of our examples use ``0``, however, ``0`` turns out to be useful\n+for implementation of type-checking. Additionally, ``0`` has been used\n+by `Conor McBride\n+<https://link.springer.com/chapter/10.1007/978-3-319-30936-1_12>`_ to\n+handle dependent types, which may matter for Dependent Haskell). In\n+both case, the use of ``0`` could be seen as an internal use, but\n+there is no real reason to deny access to the programmer. Hence it is\n+included in the syntax.\n+\n+Here is the definition of sum, product and order for this proposal's\n+multiplicities (in Haskell pseudo-syntax):\n+\n+::\n+   0 + x = x\n+   x + 0 = x\n+   _ + _ = ω\n+\n+   0 * _ = 0\n+   _ * 0 = 0\n+   1 * x = x\n+   x * 1 = 1\n+   ω * ω = ω\n+\n+   _ ⩽ ω = True\n+   x ⩽ y = x == y\n+\n+Every variable in the environment is annotated with its multiplicity,\n+which constrains how it can be used. A variable usage is said to be\n+multiplicity ``p`` in a term ``u`` if:\n+\n+- ``p=0`` and ``x`` is not free in ``u``\n+- ``p=1`` and ``u = x``\n+- ``p=p1+q*p2`` `` and ``u = u1 u2`` with ``u1 :: a :q-> b`` and the\n+  usage of ``x`` in ``u1`` is ``p1``, and in ``u2`` is ``p2``\n+- ``u = λy. v`` and the usage of ``x`` in ``v`` is ``p``.\n+\n+A variable's usage is correct if it is smaller than or equal to the\n+multiplicity annotation of the variable. Incorrect usage results in a\n+type error.\n+\n+The multiplicity of a variable introduced by a λ-abstraction is taken\n+from the surrounding typing information (typically a type annotation\n+on an equation). For instance\n+\n+::\n+\n+  foo :: A :p-> B\n+  foo x = …  -- x has multiplicity p\n+\n+The above takes care of the pure λ-calculus part of Haskell. We also\n+need to consider ``let`` and ``case``.\n+\n+A ``let`` binding is considered to have an implicit multiplicity\n+annotation (the annotation is inferred). The variables introduced by a\n+``let`` bindings with annotation ``p`` all have multiplicity\n+``p``. And the usage of ``x`` in ``let_p {y1 = u1; … ;yn = un} in v``\n+is ``p*q1 + … + p*qn + q`` where the usage of ``x`` in ``ui`` is\n+``qi`` and in ``v`` is ``q``.\n+\n+If a let has recursive binders, then ``p`` must be ``ω``.\n+\n+A ``case`` expression has an implicity multiplicity annotation, like\n+``let`` binding. It if often inferred from the type annotation of an\n+equation. The usage of ``x`` in ``case_p u of { … }`` where the usage\n+of ``x`` in ``u`` is ``q`` is ``p*q`` plus the *join* of the usage of\n+``x`` in each branch.\n+\n+The multiplicity annotation of variables introduced by a pattern depend\n+on the constructor and on the implicit annotation of the\n+``case``. Specifically in ``case_p u of {…; C x1 … xn -> …; …}`` Where ``C :: a1 :q1-> … an :qn-> A``,\n+Then ``xi`` has multiplicity annotation ``p*qi``. For instance\n+\n+::\n+\n+  bar :: (a,b) :p-> c\n+  bar (x,y) = … -- Since (,) :: a ->. b ->. (a,b), x and y have\n+                -- multiplicity p\n+\n+The type ``A->.B`` is a strengthening of ``A->B``, but the type\n+checker doesn't do subtyping. It relies on polymorphism\n+instead. However, following the definition above, note that\n+\n+::\n+\n+  f :: A ->. B\n+\n+  g :: A -> B\n+  g = f  -- should not be well-typed\n+  g x = f x  -- is well-typed\n+\n+This would be rather unfortunate: for instance a linear function in a\n+library could not be used with ``map`` from base. Which means that\n+everybody would have to start caring about linearity. Worse: every use\n+of ``map Just`` would now be untyped. Fortunately, this sort of\n+opportunity is easily detected and the former definition of ``g`` is\n+understood as the latter, well-typed, one. It means that it is always\n+safe to turn a *first-order* regular arrow ``->`` into a linear ``->.``.","path":"proposals/0000-linear-types.rst","position":null,"original_position":463,"commit_id":"2cf8196366f0eee008d7abe745c51d406d5e3601","original_commit_id":"2ecc8b194118d3584ededcef41fcfd1c9ab30596","user":{"login":"facundominguez","id":1200667,"avatar_url":"https://avatars1.githubusercontent.com/u/1200667?v=4","gravatar_id":"","url":"https://api.github.com/users/facundominguez","html_url":"https://github.com/facundominguez","followers_url":"https://api.github.com/users/facundominguez/followers","following_url":"https://api.github.com/users/facundominguez/following{/other_user}","gists_url":"https://api.github.com/users/facundominguez/gists{/gist_id}","starred_url":"https://api.github.com/users/facundominguez/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/facundominguez/subscriptions","organizations_url":"https://api.github.com/users/facundominguez/orgs","repos_url":"https://api.github.com/users/facundominguez/repos","events_url":"https://api.github.com/users/facundominguez/events{/privacy}","received_events_url":"https://api.github.com/users/facundominguez/received_events","type":"User","site_admin":false},"body":"Done.","created_at":"2017-11-07T13:48:45Z","updated_at":"2017-11-07T13:48:45Z","html_url":"https://github.com/tweag/ghc-proposals/pull/1#discussion_r149371246","pull_request_url":"https://api.github.com/repos/tweag/ghc-proposals/pulls/1","author_association":"NONE","_links":{"self":{"href":"https://api.github.com/repos/tweag/ghc-proposals/pulls/comments/149371246"},"html":{"href":"https://github.com/tweag/ghc-proposals/pull/1#discussion_r149371246"},"pull_request":{"href":"https://api.github.com/repos/tweag/ghc-proposals/pulls/1"}},"in_reply_to_id":149349571},"pull_request":{"url":"https://api.github.com/repos/tweag/ghc-proposals/pulls/1","id":150359680,"html_url":"https://github.com/tweag/ghc-proposals/pull/1","diff_url":"https://github.com/tweag/ghc-proposals/pull/1.diff","patch_url":"https://github.com/tweag/ghc-proposals/pull/1.patch","issue_url":"https://api.github.com/repos/tweag/ghc-proposals/issues/1","number":1,"state":"open","locked":false,"title":"Wip/linear types","user":{"login":"facundominguez","id":1200667,"avatar_url":"https://avatars1.githubusercontent.com/u/1200667?v=4","gravatar_id":"","url":"https://api.github.com/users/facundominguez","html_url":"https://github.com/facundominguez","followers_url":"https://api.github.com/users/facundominguez/followers","following_url":"https://api.github.com/users/facundominguez/following{/other_user}","gists_url":"https://api.github.com/users/facundominguez/gists{/gist_id}","starred_url":"https://api.github.com/users/facundominguez/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/facundominguez/subscriptions","organizations_url":"https://api.github.com/users/facundominguez/orgs","repos_url":"https://api.github.com/users/facundominguez/repos","events_url":"https://api.github.com/users/facundominguez/events{/privacy}","received_events_url":"https://api.github.com/users/facundominguez/received_events","type":"User","site_admin":false},"body":"","created_at":"2017-11-02T17:45:18Z","updated_at":"2017-11-07T13:48:45Z","closed_at":null,"merged_at":null,"merge_commit_sha":"27ef4c9a5ca08251a079bad4099cf65dda098434","assignee":null,"assignees":[],"requested_reviewers":[],"milestone":null,"commits_url":"https://api.github.com/repos/tweag/ghc-proposals/pulls/1/commits","review_comments_url":"https://api.github.com/repos/tweag/ghc-proposals/pulls/1/comments","review_comment_url":"https://api.github.com/repos/tweag/ghc-proposals/pulls/comments{/number}","comments_url":"https://api.github.com/repos/tweag/ghc-proposals/issues/1/comments","statuses_url":"https://api.github.com/repos/tweag/ghc-proposals/statuses/2cf8196366f0eee008d7abe745c51d406d5e3601","head":{"label":"tweag:wip/linear-types","ref":"wip/linear-types","sha":"2cf8196366f0eee008d7abe745c51d406d5e3601","user":{"login":"tweag","id":6057932,"avatar_url":"https://avatars3.githubusercontent.com/u/6057932?v=4","gravatar_id":"","url":"https://api.github.com/users/tweag","html_url":"https://github.com/tweag","followers_url":"https://api.github.com/users/tweag/followers","following_url":"https://api.github.com/users/tweag/following{/other_user}","gists_url":"https://api.github.com/users/tweag/gists{/gist_id}","starred_url":"https://api.github.com/users/tweag/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tweag/subscriptions","organizations_url":"https://api.github.com/users/tweag/orgs","repos_url":"https://api.github.com/users/tweag/repos","events_url":"https://api.github.com/users/tweag/events{/privacy}","received_events_url":"https://api.github.com/users/tweag/received_events","type":"Organization","site_admin":false},"repo":{"id":108869197,"name":"ghc-proposals","full_name":"tweag/ghc-proposals","owner":{"login":"tweag","id":6057932,"avatar_url":"https://avatars3.githubusercontent.com/u/6057932?v=4","gravatar_id":"","url":"https://api.github.com/users/tweag","html_url":"https://github.com/tweag","followers_url":"https://api.github.com/users/tweag/followers","following_url":"https://api.github.com/users/tweag/following{/other_user}","gists_url":"https://api.github.com/users/tweag/gists{/gist_id}","starred_url":"https://api.github.com/users/tweag/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tweag/subscriptions","organizations_url":"https://api.github.com/users/tweag/orgs","repos_url":"https://api.github.com/users/tweag/repos","events_url":"https://api.github.com/users/tweag/events{/privacy}","received_events_url":"https://api.github.com/users/tweag/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/tweag/ghc-proposals","description":"Proposed compiler and language changes for GHC and GHC/Haskell","fork":true,"url":"https://api.github.com/repos/tweag/ghc-proposals","forks_url":"https://api.github.com/repos/tweag/ghc-proposals/forks","keys_url":"https://api.github.com/repos/tweag/ghc-proposals/keys{/key_id}","collaborators_url":"https://api.github.com/repos/tweag/ghc-proposals/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/tweag/ghc-proposals/teams","hooks_url":"https://api.github.com/repos/tweag/ghc-proposals/hooks","issue_events_url":"https://api.github.com/repos/tweag/ghc-proposals/issues/events{/number}","events_url":"https://api.github.com/repos/tweag/ghc-proposals/events","assignees_url":"https://api.github.com/repos/tweag/ghc-proposals/assignees{/user}","branches_url":"https://api.github.com/repos/tweag/ghc-proposals/branches{/branch}","tags_url":"https://api.github.com/repos/tweag/ghc-proposals/tags","blobs_url":"https://api.github.com/repos/tweag/ghc-proposals/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/tweag/ghc-proposals/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/tweag/ghc-proposals/git/refs{/sha}","trees_url":"https://api.github.com/repos/tweag/ghc-proposals/git/trees{/sha}","statuses_url":"https://api.github.com/repos/tweag/ghc-proposals/statuses/{sha}","languages_url":"https://api.github.com/repos/tweag/ghc-proposals/languages","stargazers_url":"https://api.github.com/repos/tweag/ghc-proposals/stargazers","contributors_url":"https://api.github.com/repos/tweag/ghc-proposals/contributors","subscribers_url":"https://api.github.com/repos/tweag/ghc-proposals/subscribers","subscription_url":"https://api.github.com/repos/tweag/ghc-proposals/subscription","commits_url":"https://api.github.com/repos/tweag/ghc-proposals/commits{/sha}","git_commits_url":"https://api.github.com/repos/tweag/ghc-proposals/git/commits{/sha}","comments_url":"https://api.github.com/repos/tweag/ghc-proposals/comments{/number}","issue_comment_url":"https://api.github.com/repos/tweag/ghc-proposals/issues/comments{/number}","contents_url":"https://api.github.com/repos/tweag/ghc-proposals/contents/{+path}","compare_url":"https://api.github.com/repos/tweag/ghc-proposals/compare/{base}...{head}","merges_url":"https://api.github.com/repos/tweag/ghc-proposals/merges","archive_url":"https://api.github.com/repos/tweag/ghc-proposals/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/tweag/ghc-proposals/downloads","issues_url":"https://api.github.com/repos/tweag/ghc-proposals/issues{/number}","pulls_url":"https://api.github.com/repos/tweag/ghc-proposals/pulls{/number}","milestones_url":"https://api.github.com/repos/tweag/ghc-proposals/milestones{/number}","notifications_url":"https://api.github.com/repos/tweag/ghc-proposals/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/tweag/ghc-proposals/labels{/name}","releases_url":"https://api.github.com/repos/tweag/ghc-proposals/releases{/id}","deployments_url":"https://api.github.com/repos/tweag/ghc-proposals/deployments","created_at":"2017-10-30T15:20:40Z","updated_at":"2017-10-30T14:58:08Z","pushed_at":"2017-11-07T13:35:09Z","git_url":"git://github.com/tweag/ghc-proposals.git","ssh_url":"git@github.com:tweag/ghc-proposals.git","clone_url":"https://github.com/tweag/ghc-proposals.git","svn_url":"https://github.com/tweag/ghc-proposals","homepage":"http://www.haskell.org/ghc","size":433,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":1,"forks":0,"open_issues":1,"watchers":0,"default_branch":"master"}},"base":{"label":"tweag:master","ref":"master","sha":"dbf516088d2839432c9568c3d1f7ae28d46aeb43","user":{"login":"tweag","id":6057932,"avatar_url":"https://avatars3.githubusercontent.com/u/6057932?v=4","gravatar_id":"","url":"https://api.github.com/users/tweag","html_url":"https://github.com/tweag","followers_url":"https://api.github.com/users/tweag/followers","following_url":"https://api.github.com/users/tweag/following{/other_user}","gists_url":"https://api.github.com/users/tweag/gists{/gist_id}","starred_url":"https://api.github.com/users/tweag/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tweag/subscriptions","organizations_url":"https://api.github.com/users/tweag/orgs","repos_url":"https://api.github.com/users/tweag/repos","events_url":"https://api.github.com/users/tweag/events{/privacy}","received_events_url":"https://api.github.com/users/tweag/received_events","type":"Organization","site_admin":false},"repo":{"id":108869197,"name":"ghc-proposals","full_name":"tweag/ghc-proposals","owner":{"login":"tweag","id":6057932,"avatar_url":"https://avatars3.githubusercontent.com/u/6057932?v=4","gravatar_id":"","url":"https://api.github.com/users/tweag","html_url":"https://github.com/tweag","followers_url":"https://api.github.com/users/tweag/followers","following_url":"https://api.github.com/users/tweag/following{/other_user}","gists_url":"https://api.github.com/users/tweag/gists{/gist_id}","starred_url":"https://api.github.com/users/tweag/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tweag/subscriptions","organizations_url":"https://api.github.com/users/tweag/orgs","repos_url":"https://api.github.com/users/tweag/repos","events_url":"https://api.github.com/users/tweag/events{/privacy}","received_events_url":"https://api.github.com/users/tweag/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/tweag/ghc-proposals","description":"Proposed compiler and language changes for GHC and GHC/Haskell","fork":true,"url":"https://api.github.com/repos/tweag/ghc-proposals","forks_url":"https://api.github.com/repos/tweag/ghc-proposals/forks","keys_url":"https://api.github.com/repos/tweag/ghc-proposals/keys{/key_id}","collaborators_url":"https://api.github.com/repos/tweag/ghc-proposals/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/tweag/ghc-proposals/teams","hooks_url":"https://api.github.com/repos/tweag/ghc-proposals/hooks","issue_events_url":"https://api.github.com/repos/tweag/ghc-proposals/issues/events{/number}","events_url":"https://api.github.com/repos/tweag/ghc-proposals/events","assignees_url":"https://api.github.com/repos/tweag/ghc-proposals/assignees{/user}","branches_url":"https://api.github.com/repos/tweag/ghc-proposals/branches{/branch}","tags_url":"https://api.github.com/repos/tweag/ghc-proposals/tags","blobs_url":"https://api.github.com/repos/tweag/ghc-proposals/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/tweag/ghc-proposals/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/tweag/ghc-proposals/git/refs{/sha}","trees_url":"https://api.github.com/repos/tweag/ghc-proposals/git/trees{/sha}","statuses_url":"https://api.github.com/repos/tweag/ghc-proposals/statuses/{sha}","languages_url":"https://api.github.com/repos/tweag/ghc-proposals/languages","stargazers_url":"https://api.github.com/repos/tweag/ghc-proposals/stargazers","contributors_url":"https://api.github.com/repos/tweag/ghc-proposals/contributors","subscribers_url":"https://api.github.com/repos/tweag/ghc-proposals/subscribers","subscription_url":"https://api.github.com/repos/tweag/ghc-proposals/subscription","commits_url":"https://api.github.com/repos/tweag/ghc-proposals/commits{/sha}","git_commits_url":"https://api.github.com/repos/tweag/ghc-proposals/git/commits{/sha}","comments_url":"https://api.github.com/repos/tweag/ghc-proposals/comments{/number}","issue_comment_url":"https://api.github.com/repos/tweag/ghc-proposals/issues/comments{/number}","contents_url":"https://api.github.com/repos/tweag/ghc-proposals/contents/{+path}","compare_url":"https://api.github.com/repos/tweag/ghc-proposals/compare/{base}...{head}","merges_url":"https://api.github.com/repos/tweag/ghc-proposals/merges","archive_url":"https://api.github.com/repos/tweag/ghc-proposals/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/tweag/ghc-proposals/downloads","issues_url":"https://api.github.com/repos/tweag/ghc-proposals/issues{/number}","pulls_url":"https://api.github.com/repos/tweag/ghc-proposals/pulls{/number}","milestones_url":"https://api.github.com/repos/tweag/ghc-proposals/milestones{/number}","notifications_url":"https://api.github.com/repos/tweag/ghc-proposals/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/tweag/ghc-proposals/labels{/name}","releases_url":"https://api.github.com/repos/tweag/ghc-proposals/releases{/id}","deployments_url":"https://api.github.com/repos/tweag/ghc-proposals/deployments","created_at":"2017-10-30T15:20:40Z","updated_at":"2017-10-30T14:58:08Z","pushed_at":"2017-11-07T13:35:09Z","git_url":"git://github.com/tweag/ghc-proposals.git","ssh_url":"git@github.com:tweag/ghc-proposals.git","clone_url":"https://github.com/tweag/ghc-proposals.git","svn_url":"https://github.com/tweag/ghc-proposals","homepage":"http://www.haskell.org/ghc","size":433,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":1,"forks":0,"open_issues":1,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/tweag/ghc-proposals/pulls/1"},"html":{"href":"https://github.com/tweag/ghc-proposals/pull/1"},"issue":{"href":"https://api.github.com/repos/tweag/ghc-proposals/issues/1"},"comments":{"href":"https://api.github.com/repos/tweag/ghc-proposals/issues/1/comments"},"review_comments":{"href":"https://api.github.com/repos/tweag/ghc-proposals/pulls/1/comments"},"review_comment":{"href":"https://api.github.com/repos/tweag/ghc-proposals/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/tweag/ghc-proposals/pulls/1/commits"},"statuses":{"href":"https://api.github.com/repos/tweag/ghc-proposals/statuses/2cf8196366f0eee008d7abe745c51d406d5e3601"}},"author_association":"NONE"}}
{"actor":{"display_login":"facundominguez"}}