{"id":20230614,"url":"https://github.com/cdepillabout/cabal2nixwithoutifd","last_synced_at":"2025-04-10T18:05:06.588Z","repository":{"id":45290641,"uuid":"401884979","full_name":"cdepillabout/cabal2nixWithoutIFD","owner":"cdepillabout","description":null,"archived":false,"fork":false,"pushed_at":"2021-12-24T00:23:18.000Z","size":478,"stargazers_count":31,"open_issues_count":1,"forks_count":1,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-03-24T15:47:27.267Z","etag":null,"topics":["hacktoberfest","haskell","nix","purenix","purescript"],"latest_commit_sha":null,"homepage":"","language":"PureScript","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/cdepillabout.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":"2021-09-01T00:53:22.000Z","updated_at":"2025-02-04T08:54:55.000Z","dependencies_parsed_at":"2022-08-02T14:15:45.144Z","dependency_job_id":null,"html_url":"https://github.com/cdepillabout/cabal2nixWithoutIFD","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/cdepillabout%2Fcabal2nixWithoutIFD","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdepillabout%2Fcabal2nixWithoutIFD/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdepillabout%2Fcabal2nixWithoutIFD/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdepillabout%2Fcabal2nixWithoutIFD/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cdepillabout","download_url":"https://codeload.github.com/cdepillabout/cabal2nixWithoutIFD/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248265672,"owners_count":21075020,"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","purenix","purescript"],"created_at":"2024-11-14T07:43:12.300Z","updated_at":"2025-04-10T18:05:06.570Z","avatar_url":"https://github.com/cdepillabout.png","language":"PureScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# cabal2nixWithoutIFD\n\nThis repo contains a proof-of-concept for a\n[`callCabal2nix`](https://github.com/NixOS/nixpkgs/blob/d263feb6f6392939c4c5e0a2608a450f65417d18/pkgs/development/haskell-modules/make-package-set.nix#L220)\nfunction written in Nix. `callCabal2nix` uses\n[Import From Derivation (IFD)](https://blog.hercules-ci.com/2019/08/30/native-support-for-import-for-derivation/)\nand a Haskell program [cabal2nix](https://github.com/NixOS/cabal2nix) to take\na Haskell `.cabal` file (like\n[`example-cabal-library.cabal`](`./example-cabal-library/example-cabal-library.cabal`))\nand translate it into a derivation that can be built with Nix.\n\nOne unfortunate part of `callCabal2nix` is that `cabal2nix` is written in\nHaskell, so IFD must be used to build the resulting derivation.  IFD can often\nbe slower than just doing things with native Nix, and it is not allowed\nin Nixpkgs.\n\nThis repo provides a `callCabal2nixWithoutIFD` function that is written in Nix,\nso it doesn't have either of the above downsides.  Cabal files are parsed in\nNix directly, so IFD is not needed.\n\nInternally, this `callCabal2nixWithoutIFD` function is written in PureScript\nand transpiled to Nix using [PureNix](https://github.com/purenix-org/purenix).\nWriting a parser for a complicated format like a Cabal file is much more\nreasonable in a language like PureScript than Nix itself.\n\nWhile this repo is just a proof-of-concept, this approach of writing a\ncomplicated parser in PureNix could reasonably be extended to write a full\nparser for `.cabal` files.  Writing a similar parser directly in raw Nix would\nbe considerably more difficult.\n\n## Compiling PureScript Code to Nix\n\nCompiling `purescript-cabal-parser` to Nix can be done with the following\nsteps.\n\nFirst, get into a Nix devShell:\n\n```console\n$ nix develop\n```\n\nThe, change to `./purescript-cabal-parser` directory and run `spago build`:\n\n```console\n$ cd ./purescript-cabal-parser/\n$ spago build\n```\n\nThis transpiles the PureScript code to Nix.  The transpiled Nix code is placed\nin `./purescript-cabal-parser/output/`.\n\n## Running Transpiled PureScript Code\n\nThe transpiled PureScript code can be tested by using the [`test.nix`](./test.nix)\nscript.\n\nHere's a derivation for a Haskell package that was built using\n`callCabal2nixWithoutIFD`:\n\n```console\n$ nix-build ./test.nix -A exampleHaskellPackage\n...\n/nix/store/xb0yxkpzdz3zjqmcxwa9z6r6r98yfizz-example-cabal-library-0.1.0.0\n```\n\nHere's a derivation for a Haskell package that was built using\nthe normal `callCabal2nix`:\n\n```console\n$ nix-build ./test.nix -A exampleHaskellPackageWithIFD\n...\n/nix/store/xb0yxkpzdz3zjqmcxwa9z6r6r98yfizz-example-cabal-library-0.1.0.0\n```\n\nYou can disable IFD in Nix and see that the Haskell derivation built with\n`callCabal2nixWithoutIFD` still builds successfully:\n\n```console\n$ nix-build --option allow-import-from-derivation false ./test.nix -A exampleHaskellPackage\n...\n/nix/store/xb0yxkpzdz3zjqmcxwa9z6r6r98yfizz-example-cabal-library-0.1.0.0\n$ nix-build --option allow-import-from-derivation false ./test.nix -A exampleHaskellPackageWithIFD\nerror: cannot build '/nix/store/q5hq65ynrqnnnjs3kl1ggsx2pkwlw702-cabal2nix-example-cabal-library.drv'\nduring evaluation because the option 'allow-import-from-derivation' is disabled\n```\n\nI recommend reading through the [`test.nix`](./test.nix) file to see what other\nderivations have been defined that you can try building.  The file is heavily\ncommented.\n\n## Playing around in the Nix REPL\n\nYou may be interested in taking a look at the PureScript code that defines the\nabove derivations.  Most of the interesting code is in\n[`purescript-cabal-parser/src/Main.purs`](./purescript-cabal-parser/src/Main.purs).\n\nYou can load the transpiled PureScript code in a Nix REPL to play around with\nit:\n\n```console\n$ cd ./purescript-cabal-parser/\n$ nix repl ./purescript-cabal-parser/output/Main\n```\n\nThis puts you in a Nix REPL with all the functions and datatypes from the\n[`Main`](./purescript-cabal-parser/src/Main.purs) module available.\n\nFor instance, `Main` defines a function called `cabalParser`:\n\n```purescript\ncabalParser :: String -\u003e Either (Array String) CabalFile\n```\n\nThis takes the raw text of a Cabal file and parses it into a `CabalFile`\ndatatype:\n\n```purescript\ntype CabalFile =\n  { name :: String\n  , version :: String\n  , license :: License\n  , executable :: Executable\n  }\n\ndata License = LicenseBSD3\n\ntype Executable =\n  { name :: String\n  , buildDepends :: Array String\n  }\n```\n\nLet's try calling `cabalParser` from the Nix REPL:\n\n```nix\nnix-repl\u003e rawCabalFile = builtins.readFile ./\nnix-repl\u003e :p cabalParser rawCabalFile\n{ __field0 = { executable = { buildDepends = [ \"base\" \"aeson\" ]; name = \"example-cabal-library\"; }; license = { __tag = \"LicenseBSD3\"; }; name = \"example-cabal-library\"; version = \"0.1.0.0\"; }; __tag = \"Right\"; }\n```\n\nIf you squint, you can roughly see this attrset corresponds to the `CabalFile`\ndatatype.\n\nThere are lots of comments in the\n[`Main.purs`](./purescript-cabal-parser/src/Main.purs) file, so you may want to\nskim through it to see what else is available.\n\n## Caveats\n\nThe cabal parser implemented in `./purescript-cabal-parser/` is completely a\nproof-of-concept.  It only parses the absolute simplest of `.cabal` files.\nI wouldn't recommend using it any arbitrary Haskell package.\n\nHowever, I hope the PureScript code in this repository shows the potential of\nPureNix for writing things that would be difficult in raw Nix.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcdepillabout%2Fcabal2nixwithoutifd","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcdepillabout%2Fcabal2nixwithoutifd","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcdepillabout%2Fcabal2nixwithoutifd/lists"}