{"id":13681334,"url":"https://github.com/purenix-org/purenix","last_synced_at":"2025-04-04T15:12:02.414Z","repository":{"id":37687984,"uuid":"412944973","full_name":"purenix-org/purenix","owner":"purenix-org","description":"Nix backend for PureScript.  Transpile PureScript code to Nix.","archived":false,"fork":false,"pushed_at":"2024-08-26T08:49:45.000Z","size":158,"stargazers_count":313,"open_issues_count":15,"forks_count":9,"subscribers_count":10,"default_branch":"main","last_synced_at":"2025-03-28T14:11:24.360Z","etag":null,"topics":["hacktoberfest","haskell","nix","purescript","transpiler"],"latest_commit_sha":null,"homepage":"https://hackage.haskell.org/package/purenix","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/purenix-org.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2021-10-03T00:58:20.000Z","updated_at":"2025-03-22T21:19:19.000Z","dependencies_parsed_at":"2023-12-27T07:46:30.395Z","dependency_job_id":"6204f96b-81e4-4ebd-bdff-4adda855c0f6","html_url":"https://github.com/purenix-org/purenix","commit_stats":{"total_commits":153,"total_committers":4,"mean_commits":38.25,"dds":0.3464052287581699,"last_synced_commit":"29eccdfa3a18d3b107fe43aa70795ca96756db57"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purenix-org%2Fpurenix","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purenix-org%2Fpurenix/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purenix-org%2Fpurenix/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purenix-org%2Fpurenix/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/purenix-org","download_url":"https://codeload.github.com/purenix-org/purenix/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247198469,"owners_count":20900081,"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":["hacktoberfest","haskell","nix","purescript","transpiler"],"created_at":"2024-08-02T13:01:29.546Z","updated_at":"2025-04-04T15:12:02.396Z","avatar_url":"https://github.com/purenix-org.png","language":"Haskell","funding_links":[],"categories":["Haskell"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"img/purenix-icon.svg\" width=\"150\" height=\"150\" /\u003e\n\u003c/ p\u003e\n\u003ch1 align=\"center\"\u003ePureNix\u003c/h1\u003e\n\nPureNix is a Nix backend for PureScript.\n\nSometimes, you find yourself having to write Nix code that's more complicated than what the language was designed for.\nPureNix allows you to write that code in a fully-featured, strongly-typed language instead, and then compile to Nix.\nA typical example is parsing of configuration files, like [the port of cabal2nix that inspired PureNix](https://github.com/cdepillabout/cabal2nixWithoutIFD).\n\nPureNix has full support for all of PureScript's features, including data types, type classes, and calling back into Nix using the FFI.\n\nOn the [organization page for PureNix](https://github.com/purenix-org) you will find a number of packages intended to be used with PureNix, including ports of libraries like [purescript-prelude](https://github.com/purenix-org/purescript-prelude).\n\n## Usage\n\nThe easiest way to use PureNix is through Spago.\nSimply set `backend = \"purenix\"`, make sure `purenix` is available in the `PATH`, and build as normal.\n\nWhen you run `purenix`, manually or through Spago, it will look for the Purescript output directory `./output` in the current working directory.\nIt then traverses this directory structure, looks for Purescript's intermediate `corefn.json` files, transpiles the `corefn.json` files to the equivalent Nix code, and writes the output Nix code to `default.nix`.\n\nSee the [Getting Started Guide](./docs/quick-start.md) for more in-depth instructions.\n\n## Code sample\n\nPureScript source, `Main.purs`:\n\n```purescript\nmodule Main where\n\nimport Data.A as A\nimport Data.B as B\n\ngreeting :: String\ngreeting = \"Hello, world!\"\n\ndata Maybe a = Nothing | Just a\n\nfromMaybe :: forall a. a -\u003e Maybe a -\u003e a\nfromMaybe a Nothing = a\nfromMaybe _ (Just a) = a\n\nforeign import add :: Int -\u003e Int -\u003e Int\n\nfoo :: Int\nfoo = add A.bar B.baz\n```\n\nNix FFI file, `Main.nix`:\n\n```nix\n{ add = a: b: a + b; }\n```\n\nGenerated Nix:\n\n```nix\nlet\n  module =\n    { \"Data.A\" = import ../Data.A;\n      \"Data.B\" = import ../Data.B;\n    };\n  foreign = import ./foreign.nix;\n  add = foreign.add;\n  Nothing = {__tag = \"Nothing\";};\n  Just = value0:\n    { __tag = \"Just\";\n      __field0 = value0;\n    };\n  greeting = \"Hello, world!\";\n  fromMaybe = v: v1:\n    let\n      __pattern0 = __fail: if v1.__tag == \"Nothing\" then let a = v; in a else __fail;\n      __pattern1 = __fail: if v1.__tag == \"Just\" then let a = v1.__field0; in a else __fail;\n      __patternFail = builtins.throw \"Pattern match failure in src/Main.purs at 11:1 - 11:41\";\n    in\n      __pattern0 (__pattern1 __patternFail);\n  foo = add module.\"Data.A\".bar module.\"Data.B\".baz;\nin\n  {inherit greeting Nothing Just fromMaybe add foo;}\n```\n\nThere are a couple things to notice here:\n\n- PureScript built-in types like `String`, `Int`, records, and lists are converted to their corresponding Nix types, as in `greeting`.\n- Data constructors from sum types are available to easily work with in the output Nix file, like `Just` and `Nothing`, although you might want to define named field accessors.\n- Foreign imports are straightforward to define and use, like in `add` and `foo`. The FFI file gets copied into the module's output directory as `foreign.nix`.\n\n## Development\n\nYou can launch a development shell with the command `nix develop` (as long as you have flakes support enabled in Nix).\nThis puts you in a Nix shell with `cabal-install` and GHC setup to compile PureNix, as well as other helpful tools like HLint, HLS, PureScript, Spago, etc.\nFrom here you should be able to run commands like `cabal build` in order to build PureNix.\n\n## Warnings\n\n### What PureNix is and is not\n\nPureNix allows you to write code in PureScript, and then compile to Nix.\nThe degree to which you can replace existing Nix code depends on how well you can express that code in PureScript.\nFor some things, that's pretty easy, but there are many things in Nix and nixpkgs that are much harder to provide (useful) types for.\nAs such, PureNix is _not_ a complete typed replacement for Nix.\nThe goal for now is simply to allow you to take code that's tricky to write in an untyped language, and write it in a typed language instead.\n\n[The ecosystem around PureNix](https://github.com/purenix-org) is currently focused on providing PureNix ports of existing PureScript libraries.\nOver time, we hope to expand in the other direction as well, with libraries that provide typed versions of Nix-only constructs, thereby expanding the amount of Nix you can feasibly replace with PureNix, but there's still a lot to be done.\nAny help is welcome!\n\n### Laziness and memory management\n\nPureScript generally assumes that its backends perform strict evaluation, and some degree of memory management.\nNix is a lazy language however, and is happy to leak memory.\nFor most use cases this doesn't cause any issues, and in fact the laziness allows you to write more Haskell-like code than you usually would in PureScript.\n\nStill, it's good to keep these things in mind:\n\n- Like in every lazy language, you need to watch out for space leaks caused by accidentally building up large thunks.\n  PureScript does not natively have tools to deal with laziness, like bang patterns or `seq`, but you can define them yourself by e.g. pulling in `builtins.seq` through the FFI.\n\n- Long-running programs may run out of memory due to the lack of garbage collection and tail recursion.\n  If you end up writing long-running programs, like a parser that needs to process very large files, you might have to rewrite it in a way that minimizes recursion and allocation.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpurenix-org%2Fpurenix","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpurenix-org%2Fpurenix","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpurenix-org%2Fpurenix/lists"}