{"id":1132,"url":"https://github.com/robrix/Prelude","last_synced_at":"2025-07-30T20:32:34.751Z","repository":{"id":24021960,"uuid":"27406500","full_name":"robrix/Prelude","owner":"robrix","description":"Swift µframework of simple functional programming tools","archived":false,"fork":false,"pushed_at":"2018-07-19T13:21:25.000Z","size":126,"stargazers_count":408,"open_issues_count":3,"forks_count":26,"subscribers_count":19,"default_branch":"master","last_synced_at":"2024-05-09T08:03:13.124Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/robrix.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-12-02T00:05:56.000Z","updated_at":"2024-02-24T16:51:11.000Z","dependencies_parsed_at":"2022-08-22T02:20:49.772Z","dependency_job_id":null,"html_url":"https://github.com/robrix/Prelude","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robrix%2FPrelude","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robrix%2FPrelude/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robrix%2FPrelude/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robrix%2FPrelude/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/robrix","download_url":"https://codeload.github.com/robrix/Prelude/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228187535,"owners_count":17882322,"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-01-05T20:15:39.589Z","updated_at":"2024-12-04T20:31:00.991Z","avatar_url":"https://github.com/robrix.png","language":"Swift","readme":"# Prelude\n\nThis is a Swift µframework providing a number of simple functions that I use in many of my other frameworks. Rather than continue to reimplement them for each consumer, I am gathering them here together.\n\nNotably, this framework does not provide any new types, or any functions which operate on custom types; those presumably belong in µframeworks of their own.\n\n\n## Table of Contents\n\n- [Gallery](#gallery)\n\t- [`id`](#id)\n\t- [`const`](#const)\n\t- [`\u003e\u003e\u003e` and `\u003c\u003c\u003c`](#-and-)\n\t- [`fix`](#fix)\n\t- [`|\u003e` and `\u003c|`](#-and--1)\n\t- [`curry`](#curry)\n\t- [`flip`](#flip)\n\t- [`\u0026\u0026\u0026`](#-)\n\t- [`swap`](#swap)\n\t- [`first` and `second`](#first-and-second)\n- [Documentation](#documentation)\n- [Integration](#integration)\n\n\n# Gallery\n\nPrelude’s functions are infinitely useful. Here’s a gallery of just a few of the things you can do with them.\n\n\n## `id`\n\nPassing `id` as the argument to the `flattenMap` method of a [`Stream`](https://github.com/robrix/Traversal) of `Stream`s will flatten it out into a stream of all the nested elements:\n\n```swift\nfunc flatten\u003cT\u003e(stream: Stream\u003cStream\u003cT\u003e\u003e) -\u003e Stream\u003cT\u003e {\n\treturn stream.flattenMap(id)\n}\n```\n\n\n## `const`\n\nPassing the result of `const` to an [`Either`](https://github.com/robrix/Either) is convenient for transforming it into an `Optional\u003cT\u003e`:\n\n```swift\nlet result: Either\u003cNSError, String\u003e = …\nif let string = result.either(const(nil), id) {\n\tprintln(\"ohai \\($0)\")\n}\n```\n\n\n## `\u003e\u003e\u003e` and `\u003c\u003c\u003c`\n\nThe left-to-right and right-to-left composition operators (`\u003e\u003e\u003e` and `\u003c\u003c\u003c` respectively) chain operations together:\n\n```swift\nlet repl: File -\u003e String = readLine \u003e\u003e\u003e parseString \u003e\u003e\u003e evaluateAST \u003e\u003e\u003e toString\nwhile true {\n\tprintln(repl(standardInput))\n}\n```\n\n\n## `fix`\n\nYou can use `fix` to make an anonymous function which calls itself recursively:\n\n```swift\nlet factorial = fix { recur in\n\t{ n in n \u003e 0 ? n * recur(n - 1) : 1 }\n}\n```\n\n## `|\u003e` and `\u003c|`\n\nThe forward and backward application operators (`|\u003e` and `\u003c|` respectively) apply the function on the side they’re pointing at to the value on the other side.\n\nThis can sometimes make code more readable. This is particularly the case for the forward application operator. `x |\u003e f` is equivalent to `f(x)`, but it reads in the direction that the data flows. The benefit is more obvious with longer function names:\n\n```swift\n100 |\u003e toString |\u003e count // =\u003e 3\n// this is equivalent to\ncountElements(toString(100))\n```\n\nBackward application reads in the wrong direction for this—`f \u003c| x` isn’t really any improvement on `f(x)`. Unlike forward application, however, `\u003c|` can apply binary and ternary functions to their first operands. This enables you to make something like [Haskell’s operator sections](https://www.haskell.org/haskellwiki/Section_of_an_infix_operator):\n\n```swift\nlet successor: Int -\u003e Int = (+) \u003c| 1\nsuccessor(3) // =\u003e 4\nmap([1, 2, 3], (*) \u003c| 2) // =\u003e [2, 4, 6]\n```\n\nYou can also combine `|\u003e` and `\u003c|` with [`flip`](#flip) to pass data through chains of higher-order functions like `sorted`, `map`, and `reduce`:\n\n```swift\nlet result =\n\t[66, 78, 1, 95, 76]\n|\u003e\t(flip(sorted) \u003c| (\u003c)) // sort in ascending order\n|\u003e\t(flip(map) \u003c| toString) // make them into strings\n|\u003e\tString.join(\", \") // comma-separate them\n\nlet sum: [Int] -\u003e Int = flip(reduce) \u003c| (+) \u003c| 0\n```\n\nSince Swift functions can also be applied to tuples of their arguments, you can also use `|\u003e` and `\u003c|` with binary, ternary, etc. functions just by placing a tuple on the other side:\n\n```swift\n(1, 2) |\u003e (+) // =\u003e 3\n```\n\n\n## `curry`\n\nCurrying takes a function of \u003e1 parameter and returns a function of one parameter which returns a function of one parameter, and so on. That is, given `(T, U) -\u003e V`, currying returns `T -\u003e U -\u003e V`.\n\nThis is particularly useful when making more interesting functions such as [`\u003c|`](#-and--1).\n\n\n## `flip`\n\nFaux operator sectioning using `\u003c|` might be a little surprising using non-commutative operators like `-` and `/`: `(-) \u003c| 1` means `{ 1 - $0 }`, which is very different from `{ $0 - 1 }`. You can use `flip` to produce the latter:\n\n```swift\nmap([1, 2, 3], (-) \u003c| 1) // =\u003e [0, -1, -2]\nmap([1, 2, 3], flip(-) \u003c| 1) // =\u003e [0, 1, 2]\n```\n\n\n## `\u0026\u0026\u0026`\n\n`Optional` has a `map` method which is just what you need when you want to apply a function to a value if non-`nil`, or return `nil` otherwise. When you have two `Optional` values, you can use `\u0026\u0026\u0026` to combine them:\n\n```swift\nlet (x: Int?, y: Int?) = (2, 2)\n(x \u0026\u0026\u0026 y).map(+) // =\u003e .Some(4)\n```\n\n\n## `swap`\n\nSwift’s tuples are very convenient, but sometimes when you get one, it’s the wrong way around. `swap` does to tuples what `flip` does to functions: it reverses their order.\n\n```swift\nmap(enumerate(\"hello\"), swap) // =\u003e [(h, 0), (e, 1), (l, 2), (l, 3), (o, 4)]\n```\n\n## `first` and `second`\n\nGetting one value from a tuple is a common operation that can be expressed with `first` and `second` functions. Operators provide first and second values of two-elements tuple accordingly.\n\n```swift\n[(0,0), (5, 1), (9, 2)].map(second) // =\u003e [0, 1, 2]\n```\n\n# Documentation\n\nFull API documentation is in the source.\n\n\n# Integration\n\n1. Add this repository as a submodule and check out its dependencies, and/or [add it to your Cartfile](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfile) if you’re using [carthage](https://github.com/Carthage/Carthage/) to manage your dependencies.\n2. Drag `Prelude.xcodeproj` into your project or workspace.\n3. Link your target against `Prelude.framework`.\n4. Application targets should ensure that the framework gets copied into their application bundle. (Framework targets should instead require the application linking them to include Prelude.)\n\nOr use the Swift package manager and add this to your `Package.swift` file:  \n```\n  ...\n  dependencies: [\n    ...  \n    .package(url: \"https://github.com/robrix/Prelude\", \"3.0.0\" ..\u003c \"4.0.0\")\n  ],\n  targets: [\n    ...\n    .target(\n        name: \"\u003cYourTargetName\u003e\",\n        dependencies: [\"Prelude\"]),\n  ]\n```\n","funding_links":[],"categories":["Functional Programming","Libs","Libraries","Library","OOM-Leaks-Crash"],"sub_categories":["Getting Started","Other free courses","Utility","Linter","[Swift](https://developer.apple.com/swift)","Tools"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobrix%2FPrelude","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frobrix%2FPrelude","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobrix%2FPrelude/lists"}