From aaeac0cb63e74122c53bfd800e0b869d8d5160ff Mon Sep 17 00:00:00 2001 From: Jack Wines Date: Wed, 2 Aug 2023 00:07:37 -0700 Subject: [PATCH] setup nix --- .envrc | 1 + .gitignore | 2 + cabal.project.freeze | 229 ------------------------------------------- flake.lock | 60 ++++++++++++ flake.nix | 43 ++++++++ rcv-site.cabal | 2 +- src/InstantRunoff.hs | 13 +-- src/Main.hs | 2 +- 8 files changed, 112 insertions(+), 240 deletions(-) create mode 100644 .envrc delete mode 100644 cabal.project.freeze create mode 100644 flake.lock create mode 100644 flake.nix diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..44610e5 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake; diff --git a/.gitignore b/.gitignore index 9eba1ac..868cfd2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ **/dist-newstyle /state/ +/.direnv/ +/result diff --git a/cabal.project.freeze b/cabal.project.freeze deleted file mode 100644 index b82dbe7..0000000 --- a/cabal.project.freeze +++ /dev/null @@ -1,229 +0,0 @@ -active-repositories: hackage.haskell.org:merge -constraints: any.Cabal ==3.10.1.0, - any.Cabal-syntax ==3.10.1.0, - any.HUnit ==1.6.2.0, - any.OneTuple ==0.4.1.1, - any.QuickCheck ==2.14.3, - QuickCheck -old-random +templatehaskell, - any.StateVar ==1.2.2, - any.acid-state ==0.16.1.2, - acid-state -skip-state-machine-test, - any.aeson ==2.1.2.1, - aeson -cffi +ordered-keymap, - any.ansi-terminal ==1.0, - ansi-terminal -example, - any.ansi-terminal-types ==0.11.5, - any.ap-normalize ==0.1.0.1, - ap-normalize -test-with-clang, - any.appar ==0.1.8, - any.array ==0.5.5.0, - any.asn1-encoding ==0.9.6, - any.asn1-parse ==0.9.5, - any.asn1-types ==0.3.4, - any.assoc ==1.1, - assoc +tagged, - any.async ==2.2.4, - async -bench, - any.attoparsec ==0.14.4, - attoparsec -developer, - any.attoparsec-iso8601 ==1.1.0.0, - any.auto-update ==0.1.6, - any.base ==4.18.0.0, - any.base-compat ==0.12.2, - any.base-compat-batteries ==0.12.2, - any.base-orphans ==0.9.0, - any.base64-bytestring ==1.2.1.0, - any.basement ==0.0.16, - any.bifunctors ==5.5.15, - bifunctors +semigroups +tagged, - any.binary ==0.8.9.1, - any.blaze-builder ==0.4.2.2, - any.blaze-html ==0.9.1.2, - any.blaze-markup ==0.8.2.8, - any.boring ==0.2.1, - boring +tagged, - any.bsb-http-chunked ==0.0.0.4, - any.byteorder ==1.0.4, - any.bytestring ==0.11.4.0, - any.cabal-doctest ==1.0.9, - any.call-stack ==0.4.0, - any.case-insensitive ==1.2.1.0, - any.cereal ==0.5.8.3, - cereal -bytestring-builder, - any.clock ==0.8.3, - clock -llvm, - any.colour ==2.3.6, - any.commonmark ==0.2.2, - any.comonad ==5.0.8, - comonad +containers +distributive +indexed-traversable, - any.constraints ==0.13.4, - any.containers ==0.6.7, - any.contravariant ==1.5.5, - contravariant +semigroups +statevar +tagged, - any.cookie ==0.4.6, - any.cryptohash-md5 ==0.11.101.0, - any.cryptohash-sha1 ==0.11.101.0, - any.crypton ==0.31, - crypton -check_alignment +integer-gmp -old_toolchain_inliner +support_aesni +support_deepseq +support_pclmuldq +support_rdrand -support_sse +use_target_attributes, - any.crypton-x509 ==1.7.6, - any.crypton-x509-store ==1.6.9, - any.crypton-x509-validation ==1.6.12, - any.cryptonite ==0.30, - cryptonite -check_alignment +integer-gmp -old_toolchain_inliner +support_aesni +support_deepseq -support_pclmuldq +support_rdrand -support_sse +use_target_attributes, - any.data-default-class ==0.1.2.0, - any.data-fix ==0.3.2, - any.dec ==0.0.5, - any.deepseq ==1.4.8.1, - any.directory ==1.3.8.1, - any.distributive ==0.6.2.1, - distributive +semigroups +tagged, - any.dlist ==1.0, - dlist -werror, - any.easy-file ==0.2.5, - any.entropy ==0.4.1.10, - entropy -donotgetentropy, - any.exceptions ==0.10.7, - exceptions +transformers-0-4, - any.fast-logger ==3.2.1, - any.file-embed ==0.0.15.0, - any.filelock ==0.1.1.6, - any.filepath ==1.4.100.3, - filepath -cpphs, - any.generic-data ==1.1.0.0, - generic-data -enable-inspect, - any.generically ==0.1.1, - any.ghc-bignum ==1.3, - any.ghc-boot-th ==9.6.1, - any.ghc-prim ==0.10.0, - any.hashable ==1.4.2.0, - hashable +integer-gmp -random-initial-seed, - any.hourglass ==0.2.12, - any.hsc2hs ==0.68.9, - hsc2hs -in-ghc-tree, - any.http-api-data ==0.5, - http-api-data -use-text-show, - any.http-date ==0.0.11, - any.http-media ==0.8.0.0, - any.http-types ==0.12.3, - any.http2 ==4.1.4, - http2 -devel -h2spec, - any.indexed-traversable ==0.1.2.1, - any.indexed-traversable-instances ==0.1.1.2, - any.integer-gmp ==1.1, - any.integer-logarithms ==1.0.3.1, - integer-logarithms -check-bounds +integer-gmp, - any.iproute ==1.7.12, - any.lucid ==2.11.20230408, - any.lucid-htmx ==0.1.0.6, - any.memory ==0.18.0, - memory +support_bytestring +support_deepseq, - any.mime-types ==0.1.1.0, - any.mmorph ==1.2.0, - any.monad-control ==1.0.3.1, - any.mtl ==2.2.2, - any.network ==3.1.4.0, - network -devel, - any.network-bsd ==2.8.1.0, - any.network-byte-order ==0.1.6, - any.network-info ==0.2.1, - any.network-uri ==2.6.4.2, - any.old-locale ==1.0.0.7, - any.old-time ==1.1.0.3, - any.optparse-applicative ==0.18.1.0, - optparse-applicative +process, - any.parsec ==3.1.16.1, - any.pem ==0.2.4, - any.pretty ==1.1.3.6, - any.prettyprinter ==1.7.1, - prettyprinter -buildreadme +text, - any.prettyprinter-ansi-terminal ==1.1.3, - any.primitive ==0.8.0.0, - any.process ==1.6.17.0, - any.psqueues ==0.2.7.3, - any.random ==1.2.1.1, - any.recv ==0.1.0, - any.resourcet ==1.2.6, - any.rts ==1.0.2, - any.safe-exceptions ==0.1.7.3, - any.safecopy ==0.10.4.2, - any.scientific ==0.3.7.0, - scientific -bytestring-builder -integer-simple, - any.semialign ==1.3, - semialign +semigroupoids, - any.semigroupoids ==5.3.7, - semigroupoids +comonad +containers +contravariant +distributive +tagged +unordered-containers, - any.servant ==0.19.1, - any.servant-lucid ==0.9.0.6, - any.servant-server ==0.19.2, - any.show-combinators ==0.2.0.0, - any.simple-sendfile ==0.2.31, - simple-sendfile +allow-bsd -fallback, - any.singleton-bool ==0.1.6, - any.some ==1.0.5, - some +newtype-unsafe, - any.sop-core ==0.5.0.2, - any.splitmix ==0.1.0.4, - splitmix -optimised-mixer, - any.stm ==2.5.1.0, - any.streaming-commons ==0.2.2.6, - streaming-commons -use-bytestring-builder, - any.strict ==0.5, - any.string-conversions ==0.4.0.1, - any.syb ==0.7.2.3, - any.tagged ==0.8.7, - tagged +deepseq +transformers, - any.template-haskell ==2.20.0.0, - any.text ==2.0.2, - any.text-short ==0.1.5, - text-short -asserts, - any.th-abstraction ==0.5.0.0, - any.th-compat ==0.1.4, - any.th-expand-syns ==0.4.11.0, - any.these ==1.2, - any.time ==1.12.2, - any.time-compat ==1.9.6.1, - time-compat -old-locale, - any.time-manager ==0.0.0, - any.tls ==1.7.0, - tls +compat -hans +network, - any.tls-session-manager ==0.0.4, - any.transformers ==0.5.6.2, - any.transformers-base ==0.4.6, - transformers-base +orphaninstances, - any.transformers-compat ==0.7.2, - transformers-compat -five +five-three -four +generic-deriving +mtl -three -two, - any.type-equality ==1, - any.unicode-data ==0.4.0.1, - unicode-data -ucd2haskell, - any.unicode-transforms ==0.4.0.1, - unicode-transforms -bench-show -dev -has-icu -has-llvm -use-gauge, - any.unix ==2.8.1.1, - any.unix-compat ==0.7, - unix-compat -old-time, - any.unix-time ==0.4.9, - any.unliftio ==0.2.25.0, - any.unliftio-core ==0.2.1.0, - any.unordered-containers ==0.2.19.1, - unordered-containers -debug, - any.utf8-string ==1.0.2, - any.uuid ==1.3.15, - any.uuid-types ==1.0.5, - any.vault ==0.3.1.5, - vault +useghc, - any.vector ==0.13.0.0, - vector +boundschecks -internalchecks -unsafechecks -wall, - any.vector-stream ==0.1.0.0, - any.wai ==3.2.3, - any.wai-app-static ==3.1.7.4, - wai-app-static +cryptonite -print, - any.wai-extra ==3.1.13.0, - wai-extra -build-example, - any.wai-logger ==2.4.0, - any.warp ==3.3.27, - warp +allow-sendfilefd -network-bytestring -warp-debug +x509, - any.warp-tls ==3.4.0, - any.witherable ==0.4.2, - any.word8 ==0.1.3, - any.zlib ==0.6.3.0, - zlib -bundled-c-zlib -non-blocking-ffi -pkg-config -index-state: hackage.haskell.org 2023-06-17T00:34:29Z diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..1bb3800 --- /dev/null +++ b/flake.lock @@ -0,0 +1,60 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1689068808, + "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1690924695, + "narHash": "sha256-1yshNzds/qJztMoJk0Sa2xhKwSLaOAuepR6ABWbrgRU=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "7282565b1ca9ba7b293b899411e70167f4a7c1ff", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..398885b --- /dev/null +++ b/flake.nix @@ -0,0 +1,43 @@ +# SPDX-FileCopyrightText: 2021 Serokell +# +# SPDX-License-Identifier: CC0-1.0 + +{ + description = "My haskell application"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { self, nixpkgs, flake-utils }: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = nixpkgs.legacyPackages.${system}; + + haskellPackages = pkgs.haskellPackages; + + jailbreakUnbreak = pkg: + pkgs.haskell.lib.doJailbreak (pkg.overrideAttrs (_: { meta = { }; })); + + # DON'T FORGET TO PUT YOUR PACKAGE NAME HERE, REMOVING `throw` + packageName = "rcv-site"; + in { + packages.${packageName} = + haskellPackages.callCabal2nix packageName self rec { + # Dependency overrides go here + }; + + packages.default = self.packages.${system}.${packageName}; + defaultPackage = self.packages.${system}.default; + + devShells.default = pkgs.mkShell { + buildInputs = with pkgs; [ + haskellPackages.haskell-language-server # you must build it with your ghc to work + cabal-install + ]; + inputsFrom = map (__getAttr "env") (__attrValues self.packages.${system}); + }; + devShell = self.devShells.${system}.default; + }); +} diff --git a/rcv-site.cabal b/rcv-site.cabal index 52c14c2..c55ab04 100644 --- a/rcv-site.cabal +++ b/rcv-site.cabal @@ -64,7 +64,7 @@ executable rcv-site wai-app-static, wai-extra, warp, - warp-tls == 3.4.0 + warp-tls default-language: Haskell2010 other-modules: diff --git a/src/InstantRunoff.hs b/src/InstantRunoff.hs index f8b0a64..ec52245 100644 --- a/src/InstantRunoff.hs +++ b/src/InstantRunoff.hs @@ -52,19 +52,14 @@ rank votes = voteCounts :: M.Map a Word voteCounts = M.unionsWith (+) - . (candidatesStartingPoint :) + . (M.fromSet (const 0) candidates :) . map (`M.singleton` 1) . LN.toList . LN.map LN.head $ votes - -- every candidate starts with zero votes - -- there are occasionally candidates with no first choice votes at all - -- we need to know about them - candidatesStartingPoint :: M.Map a Word - candidatesStartingPoint = - M.fromSet (const 0) - -- set of all candidates on anybody's ballot - . S.unions . LN.map (S.fromList . LN.toList) $ votes + -- set of all candidates on anybody's ballot + candidates :: S.Set a + candidates = S.unions . LN.map (S.fromList . LN.toList) $ votes filterVotes :: (a -> Bool) -> LN.NonEmpty (LN.NonEmpty a) -> Maybe (LN.NonEmpty (LN.NonEmpty a)) filterVotes f = catMaybes . LN.map (LN.nonEmpty . LN.filter f) diff --git a/src/Main.hs b/src/Main.hs index 4528fb8..0cb46d4 100644 --- a/src/Main.hs +++ b/src/Main.hs @@ -55,7 +55,7 @@ results pollId = do case toNonEmptyList . P.votes $ poll of Nothing -> fullPage "poll doesn't have any votes" Just votesList -> do - let results' = IR.solve (filter (not . T.null) . LN.toList . P.options . P.createInfo $ poll) (votesList) + let results' = IR.solve (LN.filter (not . T.null) . P.options . P.createInfo $ poll) (votesList) fullPage $ do h2_ "results" toHtml $ T.append (T.pack . show . length . P.votes $ poll) " ballots submitted"