{"id":21540658,"url":"https://github.com/tchajed/coq-io","last_synced_at":"2025-04-10T03:33:55.774Z","repository":{"id":147767748,"uuid":"103777356","full_name":"tchajed/coq-io","owner":"tchajed","description":"Modeling I/O in Coq using free monads","archived":false,"fork":false,"pushed_at":"2018-07-27T16:29:59.000Z","size":20,"stargazers_count":10,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-24T04:50:52.738Z","etag":null,"topics":["coq","monads"],"latest_commit_sha":null,"homepage":"","language":"Coq","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/tchajed.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-09-16T19:10:25.000Z","updated_at":"2025-02-06T04:53:57.000Z","dependencies_parsed_at":"2023-05-10T11:30:59.415Z","dependency_job_id":null,"html_url":"https://github.com/tchajed/coq-io","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tchajed%2Fcoq-io","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tchajed%2Fcoq-io/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tchajed%2Fcoq-io/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tchajed%2Fcoq-io/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tchajed","download_url":"https://codeload.github.com/tchajed/coq-io/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248151834,"owners_count":21056174,"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":["coq","monads"],"created_at":"2024-11-24T04:19:44.883Z","updated_at":"2025-04-10T03:33:55.763Z","avatar_url":"https://github.com/tchajed.png","language":"Coq","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Free monads for modeling IO in Coq\n\nA small example of how to model various kinds of IO using a _free monad_ over primitive operations in Coq, including how to extract and run code written in this style.\n\nIn [FSCQ](https://github.com/mit-pdos/fscq), we need to model programs that have access to a disk. We write our code in a shallow embedding of programs with primitives for reading and writing to and from the disk. This shallow embedding is a free monad over the desired, primitive disk operations. We give the monadic programs a semantics as a transition system from one state to another. Programs are values in a monad, and the type argument gives the type of a return value for finished programs. The state is manipulated by the primitives, whose behavior is also specified in the semantics.\n\nThe code here has a similar model, but is written in a more general way and attempts to expose only the details needed to understand the concepts and get a simple example running. It works almost the same way as FSCQ disk programs, but is phrased in terms of accessing a single input file with a simple single-byte API.\n\n# Overview\n\nThe Coq model has a very generic definition `prog`, which takes an argument `Op : Type -\u003e Type` giving the type constructor for the primitives (the type argument indicates the return type). Primitives are chained using `Ret` and `Bind`. Then there's an execution semantics, which is expresses the behavior of a program in terms of how it transforms some state type and what return values are allowed (the semantics are relational, so non-determinism is allowed). These semantics specify how `Ret` and `Bind` work and take a parameter `step` for the behavior of the primitives.\n\nAs an example, we define `FileOp`, a set of primitives for access to a single input file. These operations have a semantics, in terms of a state which is simply a list of bytes (which we call a `File`). Then there are two example programs of type `prog FileOp T`: one copies a byte, the other is a fixpoint `countNewlines` that counts newlines in the file.\n\nOn the Haskell side, any given `prog` extracts to a Haskell data type, a sort of abstract syntax tree of operations, but with Haskell functions extracted from Gallina implementing important functionality. Due to a limitation with Coq extraction, we extract `prog` specialized to `FileOp`.\n\nThen we have some non-Coq components that won't be under verification. These are fairly simple: there's an \"interpreter\" that runs extracted `prog FileOp`'s, and then a driver program that calls the interpreter on the `countNewlines` program, with some command line parsing and file setup that falls outside of the Coq model.\n\n# Compiling\n\nRun `make` to compile the Coq code and generate the Haskell library. This compiles `Prog.v` with Coq and extracts to `word-count/src/Prog.hs`.\n\nFrom there, we have a hand-written interpreter (`word-count/src/Interpreter.hs`), and a driver program (`word-count/app/Main.hs`) around the `countNewlines` example in `Prog.v`.\n\nTo compile the driver program and produce the `word-count` binary, use Haskell Stack. Stack requires a one-time setup to download the compiler:\n\n```\ncd word-count\nstack setup\n```\n\nThen you can compile and run the binary:\n\n```\nstack build\nstack exec word-count -- \u003cfile\u003e\n```\n\nThis should give the same output as `wc -l \u003cfile\u003e`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftchajed%2Fcoq-io","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftchajed%2Fcoq-io","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftchajed%2Fcoq-io/lists"}