{"id":20230831,"url":"https://github.com/sharkdp/purescript-ctprelude","last_synced_at":"2026-03-06T17:38:40.914Z","repository":{"id":65984758,"uuid":"62589037","full_name":"sharkdp/purescript-ctprelude","owner":"sharkdp","description":"A Prelude with names from category theory","archived":false,"fork":false,"pushed_at":"2016-09-05T17:51:10.000Z","size":36,"stargazers_count":51,"open_issues_count":0,"forks_count":1,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-03-03T13:45:01.248Z","etag":null,"topics":["category-theory","purescript"],"latest_commit_sha":null,"homepage":null,"language":"PureScript","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/sharkdp.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":"2016-07-04T21:32:12.000Z","updated_at":"2024-11-25T09:00:49.000Z","dependencies_parsed_at":"2023-02-19T18:15:31.201Z","dependency_job_id":null,"html_url":"https://github.com/sharkdp/purescript-ctprelude","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/sharkdp/purescript-ctprelude","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sharkdp%2Fpurescript-ctprelude","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sharkdp%2Fpurescript-ctprelude/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sharkdp%2Fpurescript-ctprelude/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sharkdp%2Fpurescript-ctprelude/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sharkdp","download_url":"https://codeload.github.com/sharkdp/purescript-ctprelude/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sharkdp%2Fpurescript-ctprelude/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30188717,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-06T17:33:53.563Z","status":"ssl_error","status_checked_at":"2026-03-06T17:33:51.678Z","response_time":250,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["category-theory","purescript"],"created_at":"2024-11-14T07:43:52.418Z","updated_at":"2026-03-06T17:38:40.880Z","avatar_url":"https://github.com/sharkdp.png","language":"PureScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# CTPrelude\n\nAn educational Prelude for PureScript with names from category theory.\n\nThe idea of this project is to use mathematical names from category theory\nfor the types and functions that are typically defined in a Prelude or one\nof the basic libraries. For example, `Tuple` is called `Product` (with\ninfix alias ⊗) and `Either` is called `Coproduct` (with infix alias ⊕).\n`Unit`, a type with a single inhabitant, is called `One` whereas\n`Boolean` is called `Two`. The following table shows a few well-known\nPureScript types, and their (isomorphic) CTPrelude equivalent:\n\n``` purs\n         Void  ≅  Zero\n         Unit  ≅  One\n      Boolean  ≅  Two\n     Ordering  ≅  Three\n\n   Either a b  ≅  a ⊕ b\n    Tuple a b  ≅  a ⊗ b\n    These a b  ≅  a ⊕ b ⊕ (a ⊗ b)\n\nCoproduct f g  ≅  f ⊞ g\n  Product f g  ≅  f ⊠ g\n\n        Maybe  ≅  Const One ⊞ Identity\n   NonEmpty f  ≅  Identity ⊠ f\n```\n\nThis module is mainly intended for educational purposes. For some\napplications, see the file `test/Main.purs`. It demonstrates how to use\n`CTPrelude` to prove isomorphisms between types, such as\n`a ⊕ a ≅ Two ⊗ a` or a few of the above.\n\n## The category of PureScript types\n\nIn the following, we will deal with the category of PureScript types,\ncalled **Purs**. Objects in **Purs** are PureScript types like `Int`,\n`String`, `Two`, `List Two`, `Int ⊗ String`, or `Int → String`\n(function types).\n\nMorphisms in **Purs** are functions. The identity morphism is called `id`.\nComposition of morphisms is simple function composition, defined by the\n`∘` operator (which is associative).\n\n*Note*: In the following, we ignore any problems arising from bottom\nvalues.\n\n# Source code\n``` purescript\nmodule CTPrelude where\n\n```\n## Simple objects (types)\n\n### Zero\nA type with no inhabitant (the empty set). `Zero` is the *initial element*\nin **Purs** (see below). This type is also known as `Void`.\n``` purescript\ndata Zero\n\n```\n### One\nA type with a single inhabitant (a singleton set). `One` is the *terminal\nobject* in **Purs** (see below). This type is also known as `Unit`.\n``` purescript\ndata One = One\n\n```\n### Two\nA type with two inhabitants (a set with two elements). Typically known as\n`Boolean`. `Two` is isomorphic to `One ⊕ One`, i.e. `Two ≅ One ⊕ One`.\n``` purescript\ndata Two = TwoA | TwoB\n\n```\n### Three\nA type with three inhabitants. We have `Three ≅ One ⊕ Two ≅ Two ⊕ One`.\n``` purescript\ndata Three = ThreeA | ThreeB | ThreeC\n\n```\n## Identity morphism and composition\n\nThe identity morphism (or function).\n``` purescript\nid ∷ ∀ a. a → a\nid x = x\n\n```\nMorphism composition is given by function composition. Note that function\ncomposition is associative and that `id` is the neutral element of `∘`.\n``` purescript\ncompose ∷ ∀ a b c. (b → c) → (a → b) → (a → c)\ncompose f g x = f (g x)\n\ninfixr 10 compose as ∘\n\n```\n## Initial and terminal object\n\n### Initial\nIn the category of PureScript types, `Zero` is the *initial object*.\n``` purescript\ntype Initial = Zero\n\n```\n`fromInitial` (also known as `absurd`) is the unique morphism from the\n*inital object* to any other object (type). In logic (using Curry-Howard\ncorrespondence), this corresponds to \"from falsehood, anything\" or \"ex\nfalso quodlibet\".\n``` purescript\nforeign import\n  fromInitial ∷ ∀ a. Initial → a\n-- Note that `fromInitial` can never be called, because the type `Initial` has\n-- no inhabitant. The function can not be implemented in PureScript, therefore\n-- the foreign import.\n\n```\n### Terminal\nIn the category of PureScript types, `One` is the *terminal object*\n(sometimes also called final object).\n``` purescript\ntype Terminal = One\n\n```\n`toTerminal` (also known as `unit`) is the unique morphism from any object\n(type) to the terminal object.\n``` purescript\ntoTerminal ∷ ∀ a. a → Terminal\ntoTerminal _ = One\n\n```\n## Product and coproduct\n\nThe product of two types, typically known as `Tuple`. This corresponds to\nthe categorical product of two objects.\n``` purescript\ndata Product a b = Product a b\n\ninfixr 6 type Product as ⊗\ninfixr 6 Product as ⊗\n\n```\nThe coproduct (sum) of two types, typically known as `Either`. This\ncorresponds to the categorical coproduct of two objects.\n``` purescript\ndata Coproduct a b = CoproductA a | CoproductB b\n\ninfixr 5 type Coproduct as ⊕\n\n```\n## Covariant functors\n\nA typeclass for covariant endofunctors on **Purs** (i.e. functors from\n**Purs** to **Purs**). The term `Functor` is used instead of `Endofunctor`\nfor convenience.\n\nLaws:\n- Identity: `map id = id`\n- Composition: `map (f ∘ g) = map f ∘ map g`\n``` purescript\nclass Functor f where\n  map ∷ ∀ a b. (a → b) → (f a → f b)\n\ninfixl 4 map as \u003c$\u003e\n\n```\n## Contravariant functors\n\nA typeclass for contravariant endofunctors on **Purs**.\n\nLaws:\n- Identity: `cmap id = id`\n- Composition: `cmap (f ∘ g) = cmap g ∘ cmap f`\n``` purescript\nclass Contravariant f where\n  cmap ∷ ∀ a b. (a → b) → (f b → f a)\n\ninfixl 4 cmap as \u003e$\u003c\n\n```\n## Morphisms\n\nA newtype for morphisms on **Purs** (functions).\n``` purescript\nnewtype Morphism a b = Morphism (a → b)\n\ninstance functorFunction ∷ Functor ((→) a) where\n  map = (∘)\n\ninstance functorMorphism ∷ Functor (Morphism a) where\n  map g (Morphism f) = Morphism (g ∘ f)\n\n```\nA newtype for morphisms with the type arguments reversed\n``` purescript\nnewtype Reversed b a = Reversed (a → b)\n\ninstance contravariantReversed ∷ Contravariant (Reversed b) where\n  cmap g (Reversed f) = Reversed (f ∘ g)\n\n```\n## Natural transformations\n\nA natural transformation is a mapping between two functors.\n``` purescript\ntype NaturalTransformation f g = ∀ a. f a → g a\n\ninfixr 4 type NaturalTransformation as ↝\n\n```\n## Isomorphisms\n\nAn isomorphism between two types `a` and `b` is established by two\nmorphisms, `forwards ∷ a → b` and `backwards ∷ b → a`, satisfying\nthe following laws:\n- `forwards ∘ backwards = id`\n- `backwards ∘ forwards = id`\n``` purescript\ndata Iso a b = Iso (a → b) (b → a)\n\ninfix 1 type Iso as ≅\n\n```\n### forwards\nGet a function `a → b` from the isomorphism `a ≅ b`.\n``` purescript\nforwards ∷ ∀ a b. a ≅ b → a → b\nforwards (Iso fwd _) = fwd\n\n```\n### backwards\nGet a function `b → a` from the isomorphism `a ≅ b`.\n``` purescript\nbackwards ∷ ∀ a b. a ≅ b → b → a\nbackwards (Iso _ bwd) = bwd\n\n```\n### reverse\nReverse an isomorphism.\n``` purescript\nreverse ∷ ∀ a b. a ≅ b → b ≅ a\nreverse (Iso fwd bwd) = Iso bwd fwd\n\n```\n### Natural isomorphisms\nA natural isomorphism between two types `f` and `g` of kind `* → *`\nis given by two natural transformations, `forwardsN ∷ f ↝ g` and\n`backwardsN ∷ g ↝ f`, satisfying the following laws:\n- `forwardsN ∘ backwardsN = id`\n- `backwardsN ∘ forwardsN = id`\n``` purescript\ndata NaturalIso f g = NaturalIso (f ↝ g) (g ↝ f)\n\ninfix 1 type NaturalIso as ≊\n\n```\n### forwardsN\nGet the natural transformation `f ↝ g` from the isomorphism `f ≊ g`.\n``` purescript\nforwardsN ∷ ∀ f g. f ≊ g → f ↝ g\nforwardsN (NaturalIso fwd _) = fwd\n\n```\n### backwardsN\nGet the natural transformation `g ↝ f` from the isomorphism `f ≊ g`.\n``` purescript\nbackwardsN ∷ ∀ f g. f ≊ g → g ↝ f\nbackwardsN (NaturalIso _ bwd) = bwd\n\n```\n### reverseN\nReverse an isomorphism.\n``` purescript\nreverseN ∷ ∀ f g. f ≊ g → g ≊ f\nreverseN (NaturalIso fwd bwd) = NaturalIso bwd fwd\n\n```\n## Products and coproducts of functors\n\nThe product of two functors.\n``` purescript\ndata ProductF f g a = ProductF (f a) (g a)\n\ninfixl 4 type ProductF as ⊠\ninfixl 4 ProductF as ⊠\n\ninstance functorProductF ∷ (Functor f, Functor g) ⇒ Functor (ProductF f g) where\n  map f (fa ⊠ ga) = (f \u003c$\u003e fa) ⊠ (f \u003c$\u003e ga)\n\n```\nThe coproduct of two functors.\n``` purescript\ndata CoproductF f g a = CoproductFA (f a) | CoproductFB (g a)\n\ninfixl 3 type CoproductF as ⊞\n\ninstance functorFCoproduct ∷ (Functor f, Functor g) ⇒ Functor (CoproductF f g) where\n  map f (CoproductFA fa) = CoproductFA (f \u003c$\u003e fa)\n  map f (CoproductFB fb) = CoproductFB (f \u003c$\u003e fb)\n\n```\n## Composition of functors\n\nRight-to-left composition of functors. The composition of two functors is\nalways a functor.\n``` purescript\nnewtype Compose f g a = Compose (f (g a))\n\ninfixl 5 type Compose as ⊚\n\ninstance functorCompose ∷ (Functor f, Functor g) ⇒ Functor (Compose f g) where\n  map h (Compose fga) = Compose (map (map h) fga)\n\n```\n## Bifunctors\n\nA `Bifunctor` is a `Functor` from the product category\n**Purs** × **Purs** to **Purs**. A type constructor with two arguments is\na `Bifunctor` if it is covariant in each argument.\n\nLaws:\n- Identity: `bimap id id = id`\n- Composition: `bimap f1 g1 ∘ bimap f2 g2 = bimap (f1 ∘ f2) (g1 ∘ g2)`\n``` purescript\nclass Bifunctor f where\n  bimap ∷ ∀ a b c d. (a → c) → (b → d) → f a b → f c d\n\ninstance bifunctorProduct ∷ Bifunctor Product where\n  bimap f g (x ⊗ y) = f x ⊗ g y\n\ninstance bifunctorSum ∷ Bifunctor Coproduct where\n  bimap f _ (CoproductA x) = CoproductA (f x)\n  bimap _ g (CoproductB y) = CoproductB (g y)\n\n```\n## Profunctors.\n\nA `Profunctor` is a `Functor` from the product category\n**Purs**\u003csup\u003eop\u003c/sup\u003e × **Purs** to **Purs**, where the superscript *op*\nindicates the dual (opposite) category. It can also be thought of as a\n`Bifunctor` which is contravariant in its first argument and covariant in\nits second argument.\n\nLaws:\n- Identity: `dimap id id = id`\n- Composition: `dimap f1 g1 ∘ dimap f2 g2 = dimap (f2 ∘ f1) (g1 ∘ g2)`\n``` purescript\nclass Profunctor p where\n  dimap ∷ ∀ a b c d. (c → a) → (b → d) → p a b → p c d\n\ninstance profunctorFunction ∷ Profunctor (→) where\n  dimap f h g = h ∘ g ∘ f\n\n```\n### Star\n`Star` lifts functors to profunctors (forwards).\n``` purescript\nnewtype Star f a b = Star (a → f b)\n\nrunStar ∷ ∀ f a b. Star f a b → (a → f b)\nrunStar (Star fn) = fn\n\ninstance profunctorStar ∷ Functor f ⇒ Profunctor (Star f) where\n  dimap f g (Star fn) = Star (map g ∘ fn ∘ f)\n\n```\n### Costar\n`Costar` lifts functors to profunctors (backwards).\n``` purescript\nnewtype Costar f a b = Costar (f a → b)\n\nrunCostar ∷ ∀ f a b. Costar f a b → (f a → b)\nrunCostar (Costar fn) = fn\n\ninstance profunctorCostar ∷ Functor f ⇒ Profunctor (Costar f) where\n  dimap f g (Costar fn) = Costar (g ∘ fn ∘ map f)\n\n```\n### Strong\nThe `Strong` class extends `Profunctor` with combinators for working with\nproducts.\n``` purescript\nclass Profunctor p ⇐ Strong p where\n  first  ∷ ∀ a b c. p a b → p (a ⊗ c) (b ⊗ c)\n  second ∷ ∀ a b c. p b c → p (a ⊗ b) (a ⊗ c)\n\ninstance strongFunction ∷ Strong (→) where\n  first  fn (a ⊗ c) = fn a ⊗ c\n  second fn (a ⊗ c) = a ⊗ fn c\n\n```\n### Choice\nThe `Choice` class extends `Profunctor` with combinators for working with\ncoproducts.\n``` purescript\nclass Profunctor p ⇐ Choice p where\n  left  ∷ ∀ a b c. p a b → p (a ⊕ c) (b ⊕ c)\n  right ∷ ∀ a b c. p b c → p (a ⊕ b) (a ⊕ c)\n\ninstance choiceFunction ∷ Choice (→) where\n  left  fn (CoproductA x) = CoproductA (fn x)\n  left  fn (CoproductB x) = CoproductB x\n  right fn (CoproductA x) = CoproductA x\n  right fn (CoproductB x) = CoproductB (fn x)\n\n```\n### Closed\nThe `Closed` class extends `Profunctor` with a combinator to work with\nfunctions.\n``` purescript\nclass Profunctor p ⇐ Closed p where\n  closed ∷ ∀ a b x. p a b → p (x → a) (x → b)\n\ninstance closedFunction ∷ Closed Function where\n  closed = (∘)\n\n```\n## Identity and Const\n\n### Identity\nThe Identity functor.\n``` purescript\ndata Identity a = Identity a\n\ninstance functorIdentity ∷ Functor Identity where\n  map f (Identity x) = Identity (f x)\n\n```\n### runIdentity\nExtract the value from the `Identity` functor.\n``` purescript\nrunIdentity ∷ ∀ a. Identity a → a\nrunIdentity (Identity x) = x\n\n```\n### Const\nThe Constant functor.\n``` purescript\ndata Const a b = Const a\n\ninstance functorConst ∷ Functor (Const a) where\n  map _ (Const x) = Const x\n\ninstance contravariantConst ∷ Contravariant (Const a) where\n  cmap _ (Const x) = Const x\n\ninstance bifunctorConst ∷ Bifunctor Const where\n  bimap f _ (Const x) = Const (f x)\n\n```\n### runConst\nExtract the value from a `Const` functor.\n``` purescript\nrunConst ∷ ∀ a b. Const a b → a\nrunConst (Const x) = x\n\n```\n## Monad\n\nA monad is an endofunctor on **Purs**, equipped with two natural\ntransformations `pure` (often *η*) and `join` (often *µ*).\n\nLaws:\n- Right identity: `pure ↣ f = f`\n- Left identity:  `f ↣ pure = f`\n- Associativity:  `(f ↣ g) ↣ h = f ↣ (g ↣ h)`\n``` purescript\nclass Functor m ⇐ Monad m where\n  pure ∷ Identity ↝ m\n  join ∷ m ⊚ m ↝ m\n\n```\nCompose two functions with monadic return values.\n``` purescript\ncomposeKleisli ∷ ∀ m a b c. Monad m ⇒ (a → m b) → (b → m c) → a → m c\ncomposeKleisli f g a = join (Compose (g \u003c$\u003e f a))\n\ninfixr 1 composeKleisli as ↣\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsharkdp%2Fpurescript-ctprelude","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsharkdp%2Fpurescript-ctprelude","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsharkdp%2Fpurescript-ctprelude/lists"}