{"id":20642710,"url":"https://github.com/typelift/aquifer","last_synced_at":"2025-04-16T01:42:52.012Z","repository":{"id":25783097,"uuid":"29221538","full_name":"typelift/Aquifer","owner":"typelift","description":"Functional streaming abstractions in Swift","archived":false,"fork":false,"pushed_at":"2017-04-03T22:05:20.000Z","size":302,"stargazers_count":72,"open_issues_count":3,"forks_count":6,"subscribers_count":8,"default_branch":"master","last_synced_at":"2024-05-09T08:12:18.198Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/typelift.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-01-14T01:44:28.000Z","updated_at":"2024-02-29T21:39:52.000Z","dependencies_parsed_at":"2022-11-29T13:19:49.182Z","dependency_job_id":null,"html_url":"https://github.com/typelift/Aquifer","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typelift%2FAquifer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typelift%2FAquifer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typelift%2FAquifer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typelift%2FAquifer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/typelift","download_url":"https://codeload.github.com/typelift/Aquifer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224937438,"owners_count":17395121,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-16T16:09:58.021Z","updated_at":"2024-11-16T16:09:58.515Z","avatar_url":"https://github.com/typelift.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)\n[![Build Status](https://travis-ci.org/typelift/Aquifer.svg?branch=master)](https://travis-ci.org/typelift/Aquifer)\n[![Gitter chat](https://badges.gitter.im/DPVN/chat.png)](https://gitter.im/typelift/general?utm_source=share-link\u0026utm_medium=link\u0026utm_campaign=share-link)\n\n# Aquifer\n\nThis is a port of [pipes](http://hackage.haskell.org/package/pipes) (and its \nimmediate associated ecosystem) to Swift, using \n[Swiftz](https://github.com/typelift/Swiftz) and \n[Focus](https://github.com/typelift/Focus).\n\nFor those already familiar with the Haskell libraries, check out the source.  For\neverybody else, see the [Tutorial Playground](Tutorial.playground) for a\nbeginner-level introduction to the major concepts and use-cases of this library.\n\n# Introduction\n\n`Aquifer` is a collection of powerful stream processing abstractions and\na network of components dedicated to stream-like concepts such as IO,\nParser-Combinators, Data Processing, Functional Reactive Programming, and much\nmore.  The fundamental unit of abstraction is a type called `Proxy` that the\nframework further segments into 6 distinct types, each representing a specific\nkind of information flow:\n\n* `Producer`s: Types that only `yield` values.\n* `Consumer`s: Types that only `await` values.\n* `Pipes`s; Types that can both `yield` and `await` values.\n* `Client`s: Types that can `request` values and receive `response`s to those requests.\n* `Server`s: Types that can `respond` to `request`s with values.\n* `Effect`s: A computation made of pipes with all the ends properly fused that can be run to yield values.\n\nBecause a `Proxy` is very generic (weighing in at 5 type parameters!), it can\nbe quite cumbersome to work with.  To combat this, the library declares each\nof the above as `typealias`es to mark methods in the library.  Rarely will the\nfully expanded form of `Proxy` be seen by the average user.  And when it is\npresent, it is only to mark operations that can work with any of the 6 types\nenumerated above.\n\n# First Principles\n\nFor the more advanced user, `Aquifer`'s semantics can be described by a number\nof Categories.  To that end, the library includes notes and diagrams to aid\nunderstanding, and to present a detailed graphical view of its most general\nparts.  For example, this is the diagram outlining `Proxy`:\n\n```\n              Upstream | Downstream\n                  +---------+\n                  |         |\n Upstream Output \u003c==       \u003c== Downstream Input\n                  |         |\n Upstream Input  ==\u003e       ==\u003e Downstream Output\n                  |    |    |\n                  +----|----+\n                       v\n                  Final Results\n```\n\nAnd another from the `Request` Category:\n\n```\n            IS                   /===\u003eDO                     IS\n             |                  /      |                      |\n        +----|----+            /  +----|----+            +----|----+\n        |    v    |           /   |    v    |            |    v    |\n    UO \u003c==       \u003c== DI \u003c==\\ / UO\u003c==       \u003c== NI    UO \u003c==       \u003c== NI\n        |    f    |         X     |    g    |     =      | f |\u003e| g |\n    UI ==\u003e       ==\u003e DO ===/ \\ UI==\u003e       ==\u003e NO    UI ==\u003e       ==\u003e NI\n        |    |    |           \\   |    |    |            |    |    |\n        +----|----+            \\  +----|----+            +----|----+\n             v                  \\      v                      v\n             FR                  \\====\u003eDI                     FR\n```\n\nIf that all seems complicated, don't worry!  The diagrams are always accompanied\nby proper explanations of the semantics of their respective methods in *plain\nEnglish*.  If the documentation is ever unclear, feel free to ask a question,\nfile an issue, or put it in your own words in a pull request.  \n\n# Programming With Pipes\n\nBy now you may be wondering how one actually goes about using `Aquifer` to\nproduce useful programs.  Returning to the `Proxy` type from earlier, each of\nits 5 parameters is a different unhandled part of the flow of data through\na pipe that you the user must \"seal\" or \"fuse\" using the other combinators in\nthis library.  For example, the operation `yield` can be thought of as:\n\n```swift\n/// Yield leaves a hole of type A that we need to fuse somehow.\nfunc yield\u003cA\u003e(value : A) -\u003e Producer\u003cA, ()\u003e.T\n```\n\n`yield` is an operation that returns a value with a \"hole\" in it that we need to\nfill.  In fact, if we were simply to use `yield` by itself, our program would\nblock indefinitely waiting for the unfused hole to be filled!  A `yield` is\nusually connected to, naturally, a `Consumer` pipe, which itself has a hole of\ntype `A`.  Here we'll hook up the function `stdinLn` (which returns\na `Producer\u003cString, ()\u003e` that `yield`s values from stdin) to the function\n`stdoutLn` (which returns a `Consumer\u003cString, ()\u003e` that `await`s values from\nsome `Producer` and prints them to stdout) with one of many fusing operators `\u003e-\u003e`\n\n```swift\nlet pipe = stdinLn() \u003e-\u003e stdoutLn()\n```\n\nThe thing to notice about `pipe` is that Swift believes it has the type\n\n```swift\n/// How do we know everything's been fused from this type signature alone?\n///\n///   +-- X indicates the output hole has been filled; fused.\n///   |  +-- This pipe only accepts () as input; fused.\n///   |  |   +-- This pipe only accepts () as input; fused.\n///   |  |   |   +-- X indicates the ouput hole has been filled; fused.\n///   |  |   |   |  +-- This pipe ultimately returns () i.e. performs an effect.\n///   |  |   |   |  |\n///   v  v   v   v  v\nProxy\u003cNever, (), (), Never, ()\u003e\n```\n\nBy consulting the handy table of `typealias`es in [`Proxy`](Aquifer/Proxy.swift)'s\ndefinition file it's easy to see that this corresponds to the `Effect` alias.  An \n`Effect` is *only* produced when every input and output from all parts of the pipe\nhave been fused away, leaving only a program that can be run with the `runEffect` \ncombinator.  The practical effect of all of this is that `Aquifer` uses Swift's\ntype system to aid in the production of fully-formed pipes.  Failure to fuse any one\nof the input or ouput holes with a concrete type results in a type error at compile\ntime.  Thus, the goal of any `Aquifer` user is always to arrive at an `Effect`, \nbecause only `Effect`s can be run to produce meaningful output.\n\nPutting it all together yields\n\n```swift\n/// This program acts like `cat` by blitting any input from stdin to stdout.\nrunEffect \u003c| stdinLn() \u003e-\u003e stdoutLn()\n```\n\n# System Requirements\n\nAquifer supports OS X 10.9+ and iOS 7.0+.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftypelift%2Faquifer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftypelift%2Faquifer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftypelift%2Faquifer/lists"}