From 19fc2651fd85bae4ae642f12204ea2de9c3a6dee Mon Sep 17 00:00:00 2001 From: Stevan Andjelkovic Date: Thu, 22 Apr 2021 10:52:47 +0200 Subject: [PATCH] add: prototype runtime system --- src/runtime-prototype/.stylish-haskell.yaml | 25 + src/runtime-prototype/CHANGELOG.md | 5 + src/runtime-prototype/LICENSE | 3 + src/runtime-prototype/README.md | 107 + src/runtime-prototype/Setup.hs | 2 + src/runtime-prototype/app/Main.hs | 6 + src/runtime-prototype/cabal.project | 11 + src/runtime-prototype/cabal.project.freeze | 2656 +++++++++++++++++ .../src/StuntDouble/Actor.hs | 35 + .../src/StuntDouble/EventLoop.hs | 37 + .../src/StuntDouble/Message.hs | 4 + .../src/StuntDouble/Reference.hs | 11 + .../src/StuntDouble/Supervisor.hs | 215 ++ src/runtime-prototype/src/StuntDouble/Vat.hs | 213 ++ src/runtime-prototype/stunt-double.cabal | 74 + src/runtime-prototype/test/Main.hs | 9 + .../test/StuntDouble/EventLoopTest.hs | 12 + src/runtime-prototype/test/TastyDiscover.hs | 3 + 18 files changed, 3428 insertions(+) create mode 100644 src/runtime-prototype/.stylish-haskell.yaml create mode 100644 src/runtime-prototype/CHANGELOG.md create mode 100644 src/runtime-prototype/LICENSE create mode 100644 src/runtime-prototype/README.md create mode 100644 src/runtime-prototype/Setup.hs create mode 100644 src/runtime-prototype/app/Main.hs create mode 100644 src/runtime-prototype/cabal.project create mode 100644 src/runtime-prototype/cabal.project.freeze create mode 100644 src/runtime-prototype/src/StuntDouble/Actor.hs create mode 100644 src/runtime-prototype/src/StuntDouble/EventLoop.hs create mode 100644 src/runtime-prototype/src/StuntDouble/Message.hs create mode 100644 src/runtime-prototype/src/StuntDouble/Reference.hs create mode 100644 src/runtime-prototype/src/StuntDouble/Supervisor.hs create mode 100644 src/runtime-prototype/src/StuntDouble/Vat.hs create mode 100644 src/runtime-prototype/stunt-double.cabal create mode 100644 src/runtime-prototype/test/Main.hs create mode 100644 src/runtime-prototype/test/StuntDouble/EventLoopTest.hs create mode 100644 src/runtime-prototype/test/TastyDiscover.hs diff --git a/src/runtime-prototype/.stylish-haskell.yaml b/src/runtime-prototype/.stylish-haskell.yaml new file mode 100644 index 00000000..b01dbcf5 --- /dev/null +++ b/src/runtime-prototype/.stylish-haskell.yaml @@ -0,0 +1,25 @@ +steps: + - imports: + align: none + list_align: with_module_name + pad_module_names: false + long_list_align: new_line_multiline + empty_list_align: inherit + list_padding: 7 # length "import " + separate_lists: false + space_surround: false + - language_pragmas: + style: vertical + align: false + remove_redundant: true + - simple_align: + cases: false + top_level_patterns: false + records: false + - trailing_whitespace: {} + +# You need to put any language extensions that's enabled for the entire project +# here. +language_extensions: [] + +columns: 72 diff --git a/src/runtime-prototype/CHANGELOG.md b/src/runtime-prototype/CHANGELOG.md new file mode 100644 index 00000000..7ec01182 --- /dev/null +++ b/src/runtime-prototype/CHANGELOG.md @@ -0,0 +1,5 @@ +# Revision history for stunt-double + +## 0.1.0.0 -- YYYY-mm-dd + +* First version. Released on an unsuspecting world. diff --git a/src/runtime-prototype/LICENSE b/src/runtime-prototype/LICENSE new file mode 100644 index 00000000..996289e8 --- /dev/null +++ b/src/runtime-prototype/LICENSE @@ -0,0 +1,3 @@ +Copyright (c) 2021 Symbiont Inc. + +All rights reserved. \ No newline at end of file diff --git a/src/runtime-prototype/README.md b/src/runtime-prototype/README.md new file mode 100644 index 00000000..4b1de055 --- /dev/null +++ b/src/runtime-prototype/README.md @@ -0,0 +1,107 @@ +### stunt-double + +`stunt-double` is an actor implementation where the real actors can easily and +faithfully be swapped out for fakes, to make testing of distributed systems +easier. + +#### Actors + +* Erlang is perhaps the most commonly associated programming language when one + thinks of implementations of actor systems today + +* Many other programming languages have tried to copy Erlang, e.g. Scala, Cloud + Haskell, etc. + +* The concept is, of course, older: Smalltalk (1972), Hewitt, Carl; Bishop, + Peter; Steiger, Richard (1973). "A Universal Modular Actor Formalism for + Artificial Intelligence". IJCAI. + +* Erlang was influenced by Smalltalk, which many people associated with OOP but + as per Alan Key's + [email](http://lists.squeakfoundation.org/pipermail/squeak-dev/1998-October/017019.html) + the key idea is actually message passing. + +#### Interfaces (a.k.a. "behaviours") + +* Joe Armstrong's PhD thesis "Making reliable distributed systems in the + presence of software errors" written in 2003 when he was 53 years old, he + started working on telecom systems in 1981. Quite different from a typical PhD + thesis written by a 20-something year old person with no or very little + experience from industry... + +* Anyway, the thesis can perhaps best be summarised by "the big idea in Erlang + isn't messaging/actors for concurrency, but using interfaces (a.k.a. + "behaviours") to *abstract away the concurrency*" (these are not Joe's words, + but rather my interpretation) + +* "network normal form" + +* Examples of interfaces: gen_server, gen_supervisor, gen_fsm, gen_event. The + idea is that an application can be written by largely combining several + instances of these. + +* Concurrent application becomes sequential, easier to write (especially for + less experience programmers) according to Joe + +* easier to maintain, if an interface is improved or a bug fixed in it, then all + application written against the interface will benefit + +* easier to test/prove according to Joe + +* In the future work section of the thesis: "How can we program components - the + idea of a set of communicating processes leads naturally to the idea of + writing the components in different languages. How can we do this?" + +#### Deployments + +* Infrastructure is a map from machine id (ip address) to set of Vat ids + +* Deployment is a supervisor tree (each actor and supervisor has a child id) and + a map from child id to machine id and Vat id + +* Deploy git commit hashes or hashes of the AST (Unison-style)? + +* Join two deployments (make assumptions about existing deployments)? + +#### Live debugging + +* Connect to (remote) event loop +* REPL +* Check crashes that happened by checking the supervisors' logs +* Check the source code of each actor +* Check the state of each actor + +* Keep a ring buffer for each actor with the last X messages it received so we + can step back and forth through time and see how the state changed + +* Keep a ring buffer with the latest Y crashes together with a ring buffer with + the last Y messages before that crash + +#### Upgrades + +* Hot-code swapping + +* Automatic rollbacks + +#### Automatic scaling + +* E.g. kubernetes detects high resource usage on some event loop, provisions a new machine, writes to some global register that the new machine is available + +#### Protocols + +* Type system? Dynamic session types! + + +#### Capabilities + +* E programming language +* [Goblins](https://spritelyproject.org/#goblins) +* OpenBSD's [pledge](https://man.openbsd.org/pledge.2) and + [unveil](https://man.openbsd.org/unveil.2) + +#### Deterministic testing + +#### See also + +* Erlang's [supervisors](https://erlang.org/doc/man/supervisor.html); +* https://capnproto.org/ diff --git a/src/runtime-prototype/Setup.hs b/src/runtime-prototype/Setup.hs new file mode 100644 index 00000000..9a994af6 --- /dev/null +++ b/src/runtime-prototype/Setup.hs @@ -0,0 +1,2 @@ +import Distribution.Simple +main = defaultMain diff --git a/src/runtime-prototype/app/Main.hs b/src/runtime-prototype/app/Main.hs new file mode 100644 index 00000000..8db2f354 --- /dev/null +++ b/src/runtime-prototype/app/Main.hs @@ -0,0 +1,6 @@ +module Main where + +import Control.Concurrent + +main :: IO () +main = print =<< getNumCapabilities diff --git a/src/runtime-prototype/cabal.project b/src/runtime-prototype/cabal.project new file mode 100644 index 00000000..87854348 --- /dev/null +++ b/src/runtime-prototype/cabal.project @@ -0,0 +1,11 @@ +packages: . + +with-compiler: ghc-8.10.4 + +reject-unconstrained-dependencies: all + +package stunt-double + ghc-options: -Wall + +allow-older: * +allow-newer: * \ No newline at end of file diff --git a/src/runtime-prototype/cabal.project.freeze b/src/runtime-prototype/cabal.project.freeze new file mode 100644 index 00000000..6357f898 --- /dev/null +++ b/src/runtime-prototype/cabal.project.freeze @@ -0,0 +1,2656 @@ +-- NOTE: Due to revisions, this file may not work. See: +-- https://github.com/fpco/stackage-server/issues/232 + +-- Stackage snapshot from: http://www.stackage.org/snapshot/lts-17.2 +-- Please place this file next to your .cabal file as cabal.config +-- To only use tested packages, uncomment the following line: +-- remote-repo: stackage-lts-17.2:http://www.stackage.org/lts-17.2 +constraints: abstract-deque ==0.3, + abstract-par ==0.3.3, + AC-Angle ==1.0, + accuerr ==0.2.0.2, + ace ==0.6, + action-permutations ==0.0.0.1, + ad ==4.4.1, + adjunctions ==4.4, + adler32 ==0.1.2.0, + aeson ==1.5.5.1, + aeson-attoparsec ==0.0.0, + aeson-better-errors ==0.9.1.0, + aeson-casing ==0.2.0.0, + aeson-combinators ==0.0.4.0, + aeson-commit ==1.3, + aeson-compat ==0.3.9, + aeson-default ==0.9.1.0, + aeson-diff ==1.1.0.9, + aeson-generic-compat ==0.0.1.3, + aeson-lens ==0.5.0.0, + aeson-optics ==1.1.0.1, + aeson-picker ==0.1.0.5, + aeson-pretty ==0.8.8, + aeson-qq ==0.8.3, + aeson-schemas ==1.3.2, + aeson-with ==0.1.2.0, + aeson-yak ==0.1.1.3, + aeson-yaml ==1.1.0.0, + agda2lagda ==0.2020.11.1, + al ==0.1.4.2, + alarmclock ==0.7.0.5, + alerts ==0.1.2.0, + alex ==3.2.6, + alg ==0.2.13.1, + algebraic-graphs ==0.5, + Allure ==0.9.5.0, + almost-fix ==0.0.2, + alsa-core ==0.5.0.1, + alsa-mixer ==0.3.0, + alsa-pcm ==0.6.1.1, + alsa-seq ==0.6.0.7, + alternative-vector ==0.0.0, + ALUT ==2.4.0.3, + amazonka-apigateway ==1.6.1, + amazonka-application-autoscaling ==1.6.1, + amazonka-appstream ==1.6.1, + amazonka-athena ==1.6.1, + amazonka-autoscaling ==1.6.1, + amazonka-budgets ==1.6.1, + amazonka-certificatemanager ==1.6.1, + amazonka-cloudformation ==1.6.1, + amazonka-cloudfront ==1.6.1, + amazonka-cloudhsm ==1.6.1, + amazonka-cloudsearch ==1.6.1, + amazonka-cloudsearch-domains ==1.6.1, + amazonka-cloudtrail ==1.6.1, + amazonka-cloudwatch ==1.6.1, + amazonka-cloudwatch-events ==1.6.1, + amazonka-cloudwatch-logs ==1.6.1, + amazonka-codebuild ==1.6.1, + amazonka-codecommit ==1.6.1, + amazonka-codedeploy ==1.6.1, + amazonka-codepipeline ==1.6.1, + amazonka-cognito-identity ==1.6.1, + amazonka-cognito-idp ==1.6.1, + amazonka-cognito-sync ==1.6.1, + amazonka-config ==1.6.1, + amazonka-core ==1.6.1, + amazonka-datapipeline ==1.6.1, + amazonka-devicefarm ==1.6.1, + amazonka-directconnect ==1.6.1, + amazonka-discovery ==1.6.1, + amazonka-dms ==1.6.1, + amazonka-ds ==1.6.1, + amazonka-dynamodb ==1.6.1, + amazonka-dynamodb-streams ==1.6.1, + amazonka-ecr ==1.6.1, + amazonka-ecs ==1.6.1, + amazonka-efs ==1.6.1, + amazonka-elasticache ==1.6.1, + amazonka-elasticbeanstalk ==1.6.1, + amazonka-elasticsearch ==1.6.1, + amazonka-elastictranscoder ==1.6.1, + amazonka-elb ==1.6.1, + amazonka-elbv2 ==1.6.1, + amazonka-emr ==1.6.1, + amazonka-gamelift ==1.6.1, + amazonka-glacier ==1.6.1, + amazonka-glue ==1.6.1, + amazonka-health ==1.6.1, + amazonka-iam ==1.6.1, + amazonka-importexport ==1.6.1, + amazonka-inspector ==1.6.1, + amazonka-iot ==1.6.1, + amazonka-iot-dataplane ==1.6.1, + amazonka-kinesis ==1.6.1, + amazonka-kinesis-analytics ==1.6.1, + amazonka-kinesis-firehose ==1.6.1, + amazonka-kms ==1.6.1, + amazonka-lambda ==1.6.1, + amazonka-lightsail ==1.6.1, + amazonka-marketplace-analytics ==1.6.1, + amazonka-marketplace-metering ==1.6.1, + amazonka-ml ==1.6.1, + amazonka-opsworks ==1.6.1, + amazonka-opsworks-cm ==1.6.1, + amazonka-pinpoint ==1.6.1, + amazonka-polly ==1.6.1, + amazonka-rds ==1.6.1, + amazonka-redshift ==1.6.1, + amazonka-rekognition ==1.6.1, + amazonka-route53 ==1.6.1, + amazonka-route53-domains ==1.6.1, + amazonka-s3 ==1.6.1, + amazonka-sdb ==1.6.1, + amazonka-servicecatalog ==1.6.1, + amazonka-ses ==1.6.1, + amazonka-shield ==1.6.1, + amazonka-sms ==1.6.1, + amazonka-snowball ==1.6.1, + amazonka-sns ==1.6.1, + amazonka-sqs ==1.6.1, + amazonka-ssm ==1.6.1, + amazonka-stepfunctions ==1.6.1, + amazonka-storagegateway ==1.6.1, + amazonka-sts ==1.6.1, + amazonka-support ==1.6.1, + amazonka-swf ==1.6.1, + amazonka-test ==1.6.1, + amazonka-waf ==1.6.1, + amazonka-workspaces ==1.6.1, + amazonka-xray ==1.6.1, + amqp ==0.20.0.1, + amqp-utils ==0.4.4.1, + annotated-wl-pprint ==0.7.0, + ansi-terminal ==0.10.3, + ansi-wl-pprint ==0.6.9, + ANum ==0.2.0.2, + apecs ==0.9.2, + apecs-gloss ==0.2.4, + apecs-physics ==0.4.5, + api-field-json-th ==0.1.0.2, + api-maker ==0.1.0.0, + ap-normalize ==0.1.0.0, + appar ==0.1.8, + appendmap ==0.1.5, + apply-refact ==0.9.0.0, + apportionment ==0.0.0.3, + approximate ==0.3.2, + approximate-equality ==1.1.0.2, + app-settings ==0.2.0.12, + arbor-lru-cache ==0.1.1.1, + arbor-postgres ==0.0.5, + arithmoi ==0.11.0.1, + array installed, + array-memoize ==0.6.0, + arrow-extras ==0.1.0.1, + ascii ==1.0.1.0, + ascii-case ==1.0.0.2, + ascii-char ==1.0.0.6, + asciidiagram ==1.3.3.3, + ascii-group ==1.0.0.2, + ascii-predicates ==1.0.0.2, + ascii-progress ==0.3.3.0, + ascii-superset ==1.0.1.0, + ascii-th ==1.0.0.2, + asif ==6.0.4, + asn1-encoding ==0.9.6, + asn1-parse ==0.9.5, + asn1-types ==0.3.4, + assert-failure ==0.1.2.5, + assoc ==1.0.2, + astro ==0.4.2.1, + async ==2.2.2, + async-extra ==0.2.0.0, + async-pool ==0.9.1, + async-refresh ==0.3.0.0, + async-refresh-tokens ==0.4.0.0, + atom-basic ==0.2.5, + atomic-primops ==0.8.4, + atomic-write ==0.2.0.7, + attoparsec ==0.13.2.4, + attoparsec-base64 ==0.0.0, + attoparsec-binary ==0.2, + attoparsec-expr ==0.1.1.2, + attoparsec-iso8601 ==1.0.2.0, + attoparsec-path ==0.0.0.1, + audacity ==0.0.2, + aur ==7.0.5, + aura ==3.2.2, + authenticate ==1.3.5, + authenticate-oauth ==1.6.0.1, + auto ==0.4.3.1, + autoexporter ==1.1.19, + auto-update ==0.1.6, + avers ==0.0.17.1, + avro ==0.5.2.0, + aws-cloudfront-signed-cookies ==0.2.0.6, + backprop ==0.2.6.4, + backtracking ==0.1.0, + bank-holidays-england ==0.2.0.6, + barbies ==2.0.2.0, + base installed, + base16 ==0.3.0.1, + base16-bytestring ==0.1.1.7, + base16-lens ==0.1.3.0, + base32 ==0.2.0.0, + base32-lens ==0.1.0.0, + base32string ==0.9.1, + base58-bytestring ==0.1.0, + base58string ==0.10.0, + base64 ==0.4.2.3, + base64-bytestring ==1.1.0.0, + base64-bytestring-type ==1.0.1, + base64-lens ==0.3.0, + base64-string ==0.2, + base-compat ==0.11.2, + base-compat-batteries ==0.11.2, + basement ==0.0.11, + base-orphans ==0.8.4, + base-prelude ==1.4, + base-unicode-symbols ==0.2.4.2, + basic-prelude ==0.7.0, + bazel-runfiles ==0.12, + bbdb ==0.8, + bcrypt ==0.0.11, + bech32 ==1.1.0, + bech32-th ==1.0.2, + bench ==1.0.12, + benchpress ==0.2.2.15, + between ==0.11.0.0, + bibtex ==0.1.0.6, + bifunctors ==5.5.10, + bimap ==0.4.0, + bimaps ==0.1.0.2, + bimap-server ==0.1.0.1, + bin ==0.1, + binary installed, + binary-conduit ==1.3.1, + binary-ext ==2.0.4, + binary-ieee754 ==0.1.0.0, + binary-instances ==1.0.1, + binary-list ==1.1.1.2, + binary-orphans ==1.0.1, + binary-parser ==0.5.6, + binary-parsers ==0.2.4.0, + binary-search ==1.0.0.3, + binary-shared ==0.8.3, + binary-tagged ==0.3, + bindings-DSL ==1.0.25, + bindings-GLFW ==3.3.2.0, + bindings-libzip ==1.0.1, + bindings-uname ==0.1, + bins ==0.1.2.0, + bitarray ==0.0.1.1, + bits ==0.5.2, + bitset-word8 ==0.1.1.2, + bits-extra ==0.0.2.0, + bitvec ==1.0.3.0, + bitwise-enum ==1.0.0.3, + blake2 ==0.3.0, + blanks ==0.5.0, + blas-carray ==0.1.0.1, + blas-comfort-array ==0.0.0.2, + blas-ffi ==0.1, + blaze-bootstrap ==0.1.0.1, + blaze-builder ==0.4.2.1, + blaze-html ==0.9.1.2, + blaze-markup ==0.8.2.7, + blaze-svg ==0.3.6.1, + blaze-textual ==0.2.1.0, + bmp ==1.2.6.3, + BNFC ==2.9.0, + board-games ==0.3, + boltzmann-samplers ==0.1.1.0, + Boolean ==0.2.4, + boolean-like ==0.1.1.0, + boolsimplifier ==0.1.8, + boots ==0.2.0.1, + bordacount ==0.1.0.0, + boring ==0.1.3, + both ==0.1.1.1, + bound ==2.0.3, + BoundedChan ==1.0.3.0, + bounded-queue ==1.0.0, + boundingboxes ==0.2.3, + bower-json ==1.0.0.1, + boxes ==0.1.5, + brick ==0.58.1, + broadcast-chan ==0.2.1.1, + bsb-http-chunked ==0.0.0.4, + bson ==0.4.0.1, + btrfs ==0.2.0.0, + buffer-builder ==0.2.4.7, + buffer-pipe ==0.0, + bugsnag-haskell ==0.0.4.1, + bugsnag-hs ==0.2.0.3, + bugzilla-redhat ==0.3.0, + burrito ==1.2.0.0, + butcher ==1.3.3.2, + bv ==0.5, + bv-little ==1.1.1, + byteable ==0.1.1, + byte-count-reader ==0.10.1.2, + bytedump ==1.0, + byteorder ==1.0.4, + byte-order ==0.1.2.0, + bytes ==0.17, + byteset ==0.1.1.0, + bytestring installed, + bytestring-builder ==0.10.8.2.0, + bytestring-conversion ==0.3.1, + bytestring-lexing ==0.5.0.2, + bytestring-mmap ==0.2.2, + bytestring-strict-builder ==0.4.5.3, + bytestring-to-vector ==0.3.0.1, + bytestring-tree-builder ==0.2.7.7, + bz2 ==1.0.1.0, + bzlib ==0.5.1.0, + bzlib-conduit ==0.3.0.2, + c14n ==0.1.0.1, + c2hs ==0.28.7, + Cabal installed, + cabal2nix ==2.16.0, + cabal2spec ==2.6.2, + cabal-doctest ==1.0.8, + cabal-file ==0.1.1, + cabal-flatpak ==0.1.0.2, + cabal-plan ==0.7.2.0, + cabal-rpm ==2.0.7, + cache ==0.1.3.0, + cacophony ==0.10.1, + calendar-recycling ==0.0.0.1, + call-stack ==0.2.0, + can-i-haz ==0.3.1.0, + ca-province-codes ==1.0.0.0, + cardano-coin-selection ==1.0.1, + carray ==0.1.6.8, + casa-client ==0.0.1, + casa-types ==0.0.1, + cased ==0.1.0.0, + case-insensitive ==1.2.1.0, + cases ==0.1.4, + casing ==0.1.4.1, + cassava ==0.5.2.0, + cassava-conduit ==0.6.0, + cassava-megaparsec ==2.0.2, + cast ==0.1.0.2, + category ==0.2.5.0, + cayley-client ==0.4.13, + cborg ==0.2.4.0, + cborg-json ==0.2.2.0, + cereal ==0.5.8.1, + cereal-conduit ==0.8.0, + cereal-text ==0.1.0.2, + cereal-vector ==0.2.0.1, + cfenv ==0.1.0.0, + cgi ==3001.5.0.0, + chan ==0.0.4.1, + ChannelT ==0.0.0.7, + character-cases ==0.1.0.6, + charset ==0.3.7.1, + charsetdetect-ae ==1.1.0.4, + Chart ==1.9.3, + chaselev-deque ==0.5.0.5, + ChasingBottoms ==1.3.1.10, + cheapskate ==0.1.1.2, + cheapskate-highlight ==0.1.0.0, + cheapskate-lucid ==0.1.0.0, + checkers ==0.5.6, + checksum ==0.0, + chimera ==0.3.1.0, + chiphunk ==0.1.4.0, + choice ==0.2.2, + chronologique ==0.3.1.3, + chronos ==1.1.1, + chronos-bench ==0.2.0.2, + chunked-data ==0.3.1, + cipher-aes ==0.2.11, + cipher-camellia ==0.0.2, + cipher-des ==0.0.6, + cipher-rc4 ==0.1.4, + circle-packing ==0.1.0.6, + circular ==0.3.1.1, + clash-ghc ==1.2.5, + clash-lib ==1.2.5, + clash-prelude ==1.2.5, + classy-prelude ==1.5.0, + classy-prelude-conduit ==1.5.0, + clay ==0.13.3, + clientsession ==0.9.1.2, + climb ==0.3.3, + Clipboard ==2.3.2.0, + clock ==0.8, + clock-extras ==0.1.0.2, + closed ==0.2.0.1, + clumpiness ==0.17.0.2, + ClustalParser ==1.3.0, + cmark ==0.6, + cmark-gfm ==0.2.2, + cmark-lucid ==0.1.0.0, + cmdargs ==0.10.20, + codec-beam ==0.2.0, + codec-rpm ==0.2.2, + code-page ==0.2, + co-log ==0.4.0.1, + co-log-concurrent ==0.5.0.0, + co-log-core ==0.2.1.1, + Color ==0.3.0, + colorful-monoids ==0.2.1.3, + colorize-haskell ==1.0.1, + colour ==2.3.5, + colourista ==0.1.0.0, + combinatorial ==0.1.0.1, + comfort-array ==0.4, + comfort-graph ==0.0.3.1, + commutative ==0.0.2, + comonad ==5.0.8, + comonad-extras ==4.0.1, + compactmap ==0.1.4.2.1, + compensated ==0.8.1, + compiler-warnings ==0.1.0, + composable-associations ==0.1.0.0, + composable-associations-aeson ==0.1.0.0, + composite-aeson ==0.7.4.0, + composite-aeson-path ==0.7.4.0, + composite-aeson-refined ==0.7.4.0, + composite-base ==0.7.4.0, + composite-binary ==0.7.4.0, + composite-ekg ==0.7.4.0, + composite-hashable ==0.7.4.0, + composite-tuple ==0.1.2.0, + composite-xstep ==0.1.0.0, + composition ==1.0.2.1, + composition-extra ==2.0.0, + concise ==0.1.0.1, + concurrency ==1.11.0.0, + concurrent-extra ==0.7.0.12, + concurrent-output ==1.10.12, + concurrent-split ==0.0.1.1, + concurrent-supply ==0.1.8, + cond ==0.4.1.1, + conduit ==1.3.4, + conduit-algorithms ==0.0.11.0, + conduit-combinators ==1.3.0, + conduit-concurrent-map ==0.1.1, + conduit-extra ==1.3.5, + conduit-parse ==0.2.1.0, + conduit-zstd ==0.0.2.0, + conferer ==1.0.0.1, + conferer-aeson ==1.0.0.0, + conferer-hspec ==1.0.0.0, + conferer-warp ==1.0.0.0, + ConfigFile ==1.1.4, + config-ini ==0.2.4.0, + configurator ==0.3.0.0, + configurator-export ==0.1.0.1, + configurator-pg ==0.2.5, + connection ==0.3.1, + connection-pool ==0.2.2, + console-style ==0.0.2.1, + constraint ==0.1.4.0, + constraints ==0.12, + constraint-tuples ==0.1.2, + construct ==0.3, + containers installed, + contravariant ==1.5.3, + contravariant-extras ==0.3.5.2, + control-bool ==0.2.1, + control-monad-free ==0.6.2, + control-monad-omega ==0.3.2, + convertible ==1.1.1.0, + cookie ==0.4.5, + core-data ==0.2.1.9, + core-program ==0.2.6.0, + core-text ==0.3.0.0, + countable ==1.0, + country ==0.2.1, + cpio-conduit ==0.7.0, + cpphs ==1.20.9.1, + cprng-aes ==0.6.1, + cpu ==0.1.2, + cpuinfo ==0.1.0.1, + crackNum ==2.4, + crc32c ==0.0.0, + credential-store ==0.1.2, + criterion ==1.5.9.0, + criterion-measurement ==0.1.2.0, + cron ==0.7.0, + crypto-api ==0.13.3, + crypto-cipher-types ==0.0.9, + cryptocompare ==0.1.2, + crypto-enigma ==0.1.1.6, + cryptohash ==0.11.9, + cryptohash-cryptoapi ==0.1.4, + cryptohash-md5 ==0.11.100.1, + cryptohash-sha1 ==0.11.100.1, + cryptohash-sha256 ==0.11.102.0, + cryptonite ==0.27, + cryptonite-conduit ==0.2.2, + cryptonite-openssl ==0.7, + crypto-numbers ==0.2.7, + crypto-pubkey ==0.2.8, + crypto-pubkey-types ==0.4.3, + crypto-random ==0.0.9, + crypto-random-api ==0.2.0, + csp ==1.4.0, + css-syntax ==0.1.0.0, + css-text ==0.1.3.0, + csv ==0.1.2, + ctrie ==0.2, + cubicbezier ==0.6.0.6, + cubicspline ==0.1.2, + cuckoo-filter ==0.2.0.2, + cue-sheet ==2.0.1, + curl ==1.3.8, + currencies ==0.2.0.0, + currency ==0.2.0.0, + cursor ==0.3.0.0, + cursor-brick ==0.1.0.0, + cursor-fuzzy-time ==0.0.0.0, + cursor-gen ==0.3.0.0, + cutter ==0.0, + cyclotomic ==1.1.1, + czipwith ==1.0.1.3, + d10 ==0.2.1.6, + data-accessor ==0.2.3, + data-accessor-mtl ==0.2.0.4, + data-accessor-template ==0.2.1.16, + data-accessor-transformers ==0.2.1.7, + data-ascii ==1.0.0.2, + data-binary-ieee754 ==0.4.4, + data-bword ==0.1.0.1, + data-checked ==0.3, + data-clist ==0.1.2.3, + data-compat ==0.1.0.2, + data-default ==0.7.1.1, + data-default-class ==0.1.2.0, + data-default-instances-containers ==0.0.1, + data-default-instances-dlist ==0.0.1, + data-default-instances-old-locale ==0.0.1, + data-diverse ==4.7.0.0, + datadog ==0.2.5.0, + data-dword ==0.3.2, + data-endian ==0.1.1, + data-fix ==0.3.1, + data-forest ==0.1.0.8, + data-has ==0.4.0.0, + data-hash ==0.2.0.1, + data-interval ==2.0.1, + data-inttrie ==0.1.4, + data-lens-light ==0.1.2.2, + data-memocombinators ==0.5.1, + data-msgpack ==0.0.13, + data-msgpack-types ==0.0.3, + data-or ==1.0.0.5, + data-ordlist ==0.4.7.0, + data-ref ==0.0.2, + data-reify ==0.6.3, + data-serializer ==0.3.4.1, + data-textual ==0.3.0.3, + dataurl ==0.1.0.0, + DAV ==1.3.4, + DBFunctor ==0.1.1.1, + dbus ==1.2.17, + dbus-hslogger ==0.1.0.1, + debian ==4.0.2, + debian-build ==0.10.2.0, + debug-trace-var ==0.2.0, + dec ==0.0.3, + Decimal ==0.5.1, + declarative ==0.5.3, + deepseq installed, + deepseq-generics ==0.2.0.0, + deepseq-instances ==0.1.0.1, + deferred-folds ==0.9.15, + dejafu ==2.4.0.1, + dense-linear-algebra ==0.1.0.0, + depq ==0.4.1.0, + deque ==0.4.3, + deriveJsonNoPrefix ==0.1.0.1, + derive-topdown ==0.0.2.2, + deriving-aeson ==0.2.6, + deriving-compat ==0.5.10, + derulo ==1.0.9, + dhall ==1.37.1, + dhall-bash ==1.0.36, + dhall-json ==1.7.4, + dhall-lsp-server ==1.0.12, + dhall-yaml ==1.2.5, + diagrams-solve ==0.1.2, + dialogflow-fulfillment ==0.1.1.3, + di-core ==1.0.4, + dictionary-sharing ==0.1.0.0, + Diff ==0.4.0, + digest ==0.0.1.2, + digits ==0.3.1, + dimensional ==1.3, + di-monad ==1.3.1, + directory installed, + directory-tree ==0.12.1, + direct-sqlite ==2.3.26, + dirichlet ==0.1.0.2, + discount ==0.1.1, + disk-free-space ==0.1.0.1, + distributed-closure ==0.4.2.0, + distribution-nixpkgs ==1.4.0, + distribution-opensuse ==1.1.1, + distributive ==0.6.2.1, + dl-fedora ==0.7.6, + dlist ==0.8.0.8, + dlist-instances ==0.1.1.1, + dlist-nonempty ==0.1.1, + dns ==4.0.1, + dockerfile ==0.2.0, + doclayout ==0.3, + doctemplates ==0.9, + doctest ==0.16.3, + doctest-discover ==0.2.0.0, + doctest-exitcode-stdio ==0.0, + doctest-lib ==0.1, + doldol ==0.4.1.2, + do-list ==1.0.1, + do-notation ==0.1.0.2, + dot ==0.3, + dotenv ==0.8.0.7, + dotgen ==0.4.3, + dotnet-timespan ==0.0.1.0, + double-conversion ==2.0.2.0, + download ==0.3.2.7, + drinkery ==0.4, + dsp ==0.2.5.1, + dual ==0.1.1.1, + dublincore-xml-conduit ==0.1.0.2, + dunai ==0.7.0, + duration ==0.1.0.0, + dvorak ==0.1.0.0, + dynamic-state ==0.3.1, + dyre ==0.8.12, + eap ==0.9.0.2, + earcut ==0.1.0.4, + Earley ==0.13.0.1, + easy-file ==0.2.2, + Ebnf2ps ==1.0.15, + echo ==0.1.3, + ecstasy ==0.2.1.0, + ed25519 ==0.0.5.0, + edit-distance ==0.2.2.1, + edit-distance-vector ==1.0.0.4, + editor-open ==0.6.0.0, + egison ==4.1.2, + egison-pattern-src ==0.2.1.2, + egison-pattern-src-th-mode ==0.2.1.2, + either ==5.0.1.1, + either-both ==0.1.1.1, + either-unwrap ==1.1, + ekg ==0.4.0.15, + ekg-core ==0.1.1.7, + ekg-json ==0.1.0.6, + ekg-statsd ==0.2.5.0, + elerea ==2.9.0, + elf ==0.30, + eliminators ==0.7, + elm2nix ==0.2.1, + elm-bridge ==0.6.1, + elm-core-sources ==1.0.0, + elm-export ==0.6.0.1, + elynx ==0.5.0.1, + elynx-markov ==0.5.0.1, + elynx-nexus ==0.5.0.1, + elynx-seq ==0.5.0.1, + elynx-tools ==0.5.0.1, + elynx-tree ==0.5.0.1, + email-validate ==2.3.2.13, + emojis ==0.1, + enclosed-exceptions ==1.0.3, + ENIG ==0.0.1.0, + entropy ==0.4.1.6, + enummapset ==0.6.0.3, + enumset ==0.0.5, + enum-subset-generate ==0.1.0.0, + envelope ==0.2.2.0, + envparse ==0.4.1, + envy ==2.1.0.0, + epub-metadata ==4.5, + eq ==4.2.1, + equal-files ==0.0.5.3, + equational-reasoning ==0.6.0.4, + equivalence ==0.3.5, + erf ==2.0.0.0, + error-or ==0.1.2.0, + error-or-utils ==0.1.1, + errors ==2.3.0, + errors-ext ==0.4.2, + ersatz ==0.4.8, + esqueleto ==3.4.0.1, + essence-of-live-coding ==0.2.4, + essence-of-live-coding-gloss ==0.2.4, + essence-of-live-coding-pulse ==0.2.4, + essence-of-live-coding-quickcheck ==0.2.4, + etc ==0.4.1.0, + eve ==0.1.9.0, + eventful-core ==0.2.0, + eventful-test-helpers ==0.2.0, + event-list ==0.1.2, + eventstore ==1.4.1, + every ==0.0.1, + exact-combinatorics ==0.2.0.9, + exact-pi ==0.5.0.1, + exception-hierarchy ==0.1.0.4, + exception-mtl ==0.4.0.1, + exceptions ==0.10.4, + exception-transformers ==0.4.0.9, + exception-via ==0.1.0.0, + executable-path ==0.0.3.1, + exit-codes ==1.0.0, + exomizer ==1.0.0, + experimenter ==0.1.0.4, + expiring-cache-map ==0.0.6.1, + explicit-exception ==0.1.10, + exp-pairs ==0.2.1.0, + express ==0.1.3, + extended-reals ==0.2.4.0, + extensible-effects ==5.0.0.1, + extensible-exceptions ==0.1.1.4, + extra ==1.7.9, + extractable-singleton ==0.0.1, + extrapolate ==0.4.2, + fail ==4.9.0.0, + failable ==1.2.4.0, + fakedata ==0.8.0, + fakedata-parser ==0.1.0.0, + fakefs ==0.3.0.2, + fakepull ==0.3.0.2, + fast-digits ==0.3.0.0, + fast-logger ==3.0.2, + fast-math ==1.0.2, + fb ==2.1.1, + feature-flags ==0.1.0.1, + fedora-dists ==1.1.2, + fedora-haskell-tools ==0.9, + feed ==1.3.0.1, + FenwickTree ==0.1.2.1, + fft ==0.1.8.6, + fgl ==5.7.0.3, + file-embed ==0.0.13.0, + file-embed-lzma ==0, + filelock ==0.1.1.5, + filemanip ==0.3.6.3, + file-modules ==0.1.2.4, + filepath installed, + file-path-th ==0.1.0.0, + filepattern ==0.1.2, + fileplow ==0.1.0.0, + filtrable ==0.1.4.0, + fin ==0.1.1, + FindBin ==0.0.5, + fingertree ==0.1.4.2, + finite-typelits ==0.1.4.2, + first-class-families ==0.8.0.0, + first-class-patterns ==0.3.2.5, + fitspec ==0.4.8, + fixed ==0.3, + fixed-length ==0.2.2, + fixed-vector ==1.2.0.0, + fixed-vector-hetero ==0.6.0.0, + flac ==0.2.0, + flac-picture ==0.1.2, + flags-applicative ==0.1.0.2, + flat ==0.4.4, + flat-mcmc ==1.5.2, + flexible-defaults ==0.0.3, + FloatingHex ==0.5, + floatshow ==0.2.4, + flow ==1.0.21, + flush-queue ==1.0.0, + fmlist ==0.9.4, + fmt ==0.6.1.2, + fn ==0.3.0.2, + focus ==1.0.2, + focuslist ==0.1.0.2, + foldable1 ==0.1.0.0, + fold-debounce ==0.2.0.9, + fold-debounce-conduit ==0.2.0.5, + foldl ==1.4.10, + folds ==0.7.5, + follow-file ==0.0.3, + FontyFruity ==0.5.3.5, + foreign-store ==0.2, + ForestStructures ==0.0.1.0, + forkable-monad ==0.2.0.3, + forma ==1.1.3, + format-numbers ==0.1.0.1, + formatting ==6.3.7, + foundation ==0.0.25, + free ==5.1.5, + free-categories ==0.2.0.2, + freenect ==1.2.1, + freer-simple ==1.2.1.1, + freetype2 ==0.2.0, + free-vl ==0.1.4, + friendly-time ==0.4.1, + from-sum ==0.2.3.0, + frontmatter ==0.1.0.2, + fsnotify ==0.3.0.1, + fsnotify-conduit ==0.1.1.1, + ftp-client ==0.5.1.4, + ftp-client-conduit ==0.5.0.5, + funcmp ==1.9, + function-builder ==0.3.0.1, + functor-classes-compat ==1, + fusion-plugin ==0.2.2, + fusion-plugin-types ==0.1.0, + fuzzcheck ==0.1.1, + fuzzy ==0.1.0.0, + fuzzy-dates ==0.1.1.2, + fuzzyset ==0.2.0, + fuzzy-time ==0.1.0.0, + gauge ==0.2.5, + gd ==3000.7.3, + gdp ==0.0.3.0, + general-games ==1.1.1, + generic-aeson ==0.2.0.11, + generic-arbitrary ==0.1.0, + generic-constraints ==1.1.1.1, + generic-data ==0.9.2.0, + generic-data-surgery ==0.3.0.0, + generic-deriving ==1.13.1, + generic-lens ==2.0.0.0, + generic-lens-core ==2.0.0.0, + generic-monoid ==0.1.0.1, + generic-optics ==2.0.0.0, + GenericPretty ==1.2.2, + generic-random ==1.3.0.1, + generics-sop ==0.5.1.0, + generics-sop-lens ==0.2.0.1, + geniplate-mirror ==0.7.7, + genvalidity ==0.11.0.0, + genvalidity-aeson ==0.3.0.0, + genvalidity-bytestring ==0.6.0.0, + genvalidity-containers ==0.9.0.0, + genvalidity-criterion ==0.2.0.0, + genvalidity-hspec ==0.7.0.4, + genvalidity-hspec-aeson ==0.3.1.1, + genvalidity-hspec-binary ==0.2.0.4, + genvalidity-hspec-cereal ==0.2.0.4, + genvalidity-hspec-hashable ==0.2.0.5, + genvalidity-hspec-optics ==0.1.1.2, + genvalidity-hspec-persistent ==0.0.0.1, + genvalidity-mergeful ==0.2.0.0, + genvalidity-mergeless ==0.2.0.0, + genvalidity-path ==0.3.0.4, + genvalidity-property ==0.5.0.1, + genvalidity-scientific ==0.2.1.1, + genvalidity-text ==0.7.0.2, + genvalidity-time ==0.3.0.0, + genvalidity-typed-uuid ==0.0.0.2, + genvalidity-unordered-containers ==0.3.0.1, + genvalidity-uuid ==0.1.0.4, + genvalidity-vector ==0.3.0.1, + geojson ==4.0.2, + getopt-generics ==0.13.0.4, + ghc-byteorder ==4.11.0.0.10, + ghc-check ==0.5.0.3, + ghc-compact installed, + ghc-core ==0.5.6, + ghc-events ==0.15.1, + ghc-exactprint ==0.6.3.4, + ghcid ==0.8.7, + ghci-hexcalc ==0.1.1.0, + ghcjs-codemirror ==0.0.0.2, + ghc-lib ==8.10.3.20201220, + ghc-lib-parser ==8.10.3.20201220, + ghc-lib-parser-ex ==8.10.0.17, + ghc-parser ==0.2.2.0, + ghc-paths ==0.1.0.12, + ghc-prim installed, + ghc-prof ==1.4.1.7, + ghc-source-gen ==0.4.0.0, + ghc-syntax-highlighter ==0.0.6.0, + ghc-tcplugins-extra ==0.4.1, + ghc-trace-events ==0.1.2.1, + ghc-typelits-extra ==0.4.2, + ghc-typelits-knownnat ==0.7.4, + ghc-typelits-natnormalise ==0.7.3, + ghc-typelits-presburger ==0.5.2.0, + ghost-buster ==0.1.1.0, + gi-atk ==2.0.22, + gi-cairo ==1.0.24, + gi-cairo-connector ==0.1.0, + gi-cairo-render ==0.1.0, + gi-dbusmenu ==0.4.8, + gi-dbusmenugtk3 ==0.4.9, + gi-gdk ==3.0.23, + gi-gdkpixbuf ==2.0.24, + gi-gdkx11 ==3.0.10, + gi-gio ==2.0.27, + gi-glib ==2.0.24, + gi-gobject ==2.0.25, + gi-graphene ==1.0.2, + gi-gtk ==3.0.36, + gi-gtk-hs ==0.3.9, + gi-harfbuzz ==0.0.3, + ginger ==0.10.1.0, + gingersnap ==0.3.1.0, + gi-pango ==1.0.23, + githash ==0.1.5.0, + github ==0.26, + github-release ==1.3.5, + github-rest ==1.0.3, + github-types ==0.2.1, + github-webhooks ==0.15.0, + gitlab-haskell ==0.2.5, + gitrev ==1.3.1, + gi-xlib ==2.0.9, + gl ==0.9, + glabrous ==2.0.2, + GLFW-b ==3.3.0.0, + Glob ==0.10.1, + gloss ==1.13.2.1, + gloss-rendering ==1.13.1.1, + GLURaw ==2.0.0.4, + GLUT ==2.7.0.16, + gluturtle ==0.0.58.1, + gnuplot ==0.5.6.1, + google-isbn ==1.0.3, + gothic ==0.1.5, + gpolyline ==0.1.0.1, + graph-core ==0.3.0.0, + graphite ==0.10.0.1, + graphql-client ==1.1.0, + graphs ==0.7.1, + graphviz ==2999.20.1.0, + graph-wrapper ==0.2.6.0, + gravatar ==0.8.0, + greskell ==1.2.0.0, + greskell-core ==0.1.3.5, + greskell-websocket ==0.1.2.5, + groom ==0.1.2.1, + group-by-date ==0.1.0.4, + groups ==0.5.2, + gtk-sni-tray ==0.1.6.0, + gtk-strut ==0.1.3.0, + guarded-allocation ==0.0.1, + H ==0.9.0.1, + hackage-db ==2.1.0, + hackage-security ==0.6.0.1, + haddock-library ==1.9.0, + hadolint ==1.19.0, + hadoop-streaming ==0.2.0.3, + hakyll-convert ==0.3.0.3, + half ==0.3.1, + hall-symbols ==0.1.0.6, + hamtsolo ==1.0.3, + HandsomeSoup ==0.4.2, + hapistrano ==0.4.1.2, + happstack-server ==7.7.0, + happy ==1.20.0, + HasBigDecimal ==0.1.1, + hashable ==1.3.0.0, + hashable-time ==0.2.0.2, + hashids ==1.0.2.4, + hashing ==0.1.0.1, + hashmap ==1.3.3, + hashtables ==1.2.4.1, + haskeline ==0.8.1.1, + haskell-gi ==0.24.7, + haskell-gi-base ==0.24.5, + haskell-gi-overloading ==1.0, + haskell-import-graph ==1.0.4, + haskell-lexer ==1.1, + haskell-lsp ==0.22.0.0, + haskell-lsp-types ==0.22.0.0, + haskell-names ==0.9.9, + haskell-src-exts ==1.23.1, + haskell-src-exts-util ==0.2.5, + haskell-src-meta ==0.8.5, + haskey-btree ==0.3.0.1, + hasql ==1.4.4.2, + hasql-notifications ==0.1.0.0, + hasql-optparse-applicative ==0.3.0.6, + hasql-pool ==0.5.2, + hasql-queue ==1.2.0.2, + hasql-transaction ==1.0.0.1, + hasty-hamiltonian ==1.3.3, + HaTeX ==3.22.3.0, + HaXml ==1.25.5, + haxr ==3000.11.4.1, + HCodecs ==0.5.2, + hdaemonize ==0.5.6, + HDBC ==2.4.0.3, + HDBC-session ==0.1.2.0, + headroom ==0.3.2.0, + heap ==1.0.4, + heaps ==0.3.6.1, + hebrew-time ==0.1.2, + hedgehog ==1.0.4, + hedgehog-corpus ==0.2.0, + hedgehog-fakedata ==0.0.1.4, + hedgehog-fn ==1.0, + hedgehog-quickcheck ==0.1.1, + hedis ==0.14.2, + hedn ==0.3.0.2, + here ==1.2.13, + heredoc ==0.2.0.0, + heterocephalus ==1.0.5.4, + hexml ==0.3.4, + hexml-lens ==0.2.1, + hexpat ==0.20.13, + hexstring ==0.11.1, + hformat ==0.3.3.1, + hfsevents ==0.1.6, + hgeometry ==0.11.0.0, + hgeometry-combinatorial ==0.11.0.0, + hgrev ==0.2.6, + hidapi ==0.1.5, + hie-bios ==0.7.2, + hi-file-parser ==0.1.0.0, + higher-leveldb ==0.6.0.0, + highlighting-kate ==0.6.4, + hinfo ==0.0.3.0, + hinotify ==0.4.1, + hint ==0.9.0.3, + hjsmin ==0.2.0.4, + hkd-default ==1.1.0.0, + hkgr ==0.2.6.1, + hledger ==1.20.4, + hledger-iadd ==1.3.12, + hledger-interest ==1.6.0, + hledger-lib ==1.20.4, + hledger-stockquotes ==0.1.1.0, + hledger-ui ==1.20.4, + hledger-web ==1.20.4, + hlibcpuid ==0.2.0, + hlibgit2 ==0.18.0.16, + hlibsass ==0.1.10.1, + hlint ==3.2.7, + hmatrix ==0.20.1, + hmatrix-backprop ==0.1.3.0, + hmatrix-gsl ==0.19.0.1, + hmatrix-gsl-stats ==0.4.1.8, + hmatrix-morpheus ==0.1.1.2, + hmatrix-vector-sized ==0.1.3.0, + hmm-lapack ==0.4, + hmpfr ==0.4.4, + hnix-store-core ==0.2.0.0, + hnock ==0.4.0, + hoauth2 ==1.16.0, + hocon ==0.1.0.4, + hoogle ==5.0.18.1, + hOpenPGP ==2.9.5, + hopenpgp-tools ==0.23.6, + hopenssl ==2.2.4, + hopfli ==0.2.2.1, + hosc ==0.18.1, + hostname ==1.0, + hostname-validate ==1.0.0, + hourglass ==0.2.12, + hourglass-orphans ==0.1.0.0, + hp2pretty ==0.9, + hpack ==0.34.3, + hpack-dhall ==0.5.2, + hpc-codecov ==0.2.0.1, + hpc-lcov ==1.0.1, + hprotoc ==2.4.17, + hruby ==0.3.8, + hsass ==0.8.0, + hs-bibutils ==6.10.0.0, + hsc2hs ==0.68.7, + hscolour ==1.24.4, + hsdns ==1.8, + hsebaysdk ==0.4.1.0, + hsemail ==2.2.1, + hs-functors ==0.1.7.1, + hs-GeoIP ==0.3, + hsini ==0.5.1.2, + hsinstall ==2.6, + HSlippyMap ==3.0.1, + hslogger ==1.3.1.0, + hslua ==1.2.0, + hslua-aeson ==1.0.3.1, + hslua-module-doclayout ==0.2.0.1, + hslua-module-system ==0.2.2.1, + hslua-module-text ==0.3.0.1, + HsOpenSSL ==0.11.5.1, + HsOpenSSL-x509-system ==0.1.0.4, + hsp ==0.10.0, + hspec ==2.7.8, + hspec-attoparsec ==0.1.0.2, + hspec-checkers ==0.1.0.2, + hspec-contrib ==0.5.1, + hspec-core ==2.7.8, + hspec-discover ==2.7.8, + hspec-expectations ==0.8.2, + hspec-expectations-lifted ==0.10.0, + hspec-expectations-pretty-diff ==0.7.2.5, + hspec-golden ==0.1.0.3, + hspec-golden-aeson ==0.7.0.0, + hspec-hedgehog ==0.0.1.2, + hspec-leancheck ==0.0.4, + hspec-megaparsec ==2.2.0, + hspec-meta ==2.6.0, + hspec-need-env ==0.1.0.5, + hspec-parsec ==0, + hspec-smallcheck ==0.5.2, + hspec-tables ==0.0.1, + hspec-wai ==0.10.1, + hspec-wai-json ==0.10.1, + hs-php-session ==0.0.9.3, + hsshellscript ==3.4.5, + HStringTemplate ==0.8.7, + HSvm ==0.1.1.3.22, + HsYAML ==0.2.1.0, + HsYAML-aeson ==0.2.0.0, + hsyslog ==5.0.2, + htaglib ==1.2.0, + html ==1.0.1.2, + html-conduit ==1.3.2.1, + html-entities ==1.1.4.3, + html-entity-map ==0.1.0.0, + htoml ==1.0.0.3, + HTTP ==4000.3.15, + http2 ==2.0.5, + http-api-data ==0.4.1.1, + http-client ==0.6.4.1, + http-client-openssl ==0.3.2.0, + http-client-overrides ==0.1.1.0, + http-client-tls ==0.3.5.3, + http-common ==0.8.2.1, + http-conduit ==2.3.7.4, + http-date ==0.0.10, + http-directory ==0.1.8, + http-download ==0.2.0.0, + httpd-shed ==0.4.1.1, + http-link-header ==1.0.3.1, + http-media ==0.8.0.0, + http-query ==0.1.0, + http-reverse-proxy ==0.6.0, + http-streams ==0.8.7.2, + http-types ==0.12.3, + human-readable-duration ==0.2.1.4, + HUnit ==1.6.1.0, + HUnit-approx ==1.1.1.1, + hunit-dejafu ==2.0.0.4, + hvect ==0.4.0.0, + hvega ==0.11.0.0, + hw-balancedparens ==0.4.1.1, + hw-bits ==0.7.2.1, + hw-conduit ==0.2.1.0, + hw-conduit-merges ==0.2.1.0, + hw-diagnostics ==0.0.1.0, + hw-dsv ==0.4.1.0, + hweblib ==0.6.3, + hw-eliasfano ==0.1.2.0, + hw-excess ==0.2.3.0, + hw-fingertree ==0.1.2.0, + hw-fingertree-strict ==0.1.2.0, + hw-hedgehog ==0.1.1.0, + hw-hspec-hedgehog ==0.1.1.0, + hw-int ==0.0.2.0, + hw-ip ==2.4.2.0, + hw-json ==1.3.2.2, + hw-json-simd ==0.1.1.0, + hw-json-simple-cursor ==0.1.1.0, + hw-json-standard-cursor ==0.2.3.1, + hw-kafka-client ==4.0.3, + hw-mquery ==0.2.1.0, + hw-packed-vector ==0.2.1.0, + hw-parser ==0.1.1.0, + hw-prim ==0.6.3.0, + hw-rankselect ==0.13.4.0, + hw-rankselect-base ==0.3.4.1, + hw-simd ==0.1.2.0, + hw-streams ==0.0.1.0, + hw-string-parse ==0.0.0.4, + hw-succinct ==0.1.0.1, + hw-xml ==0.5.1.0, + hxt ==9.3.1.18, + hxt-charproperties ==9.4.0.0, + hxt-css ==0.1.0.3, + hxt-curl ==9.1.1.1, + hxt-expat ==9.1.1, + hxt-http ==9.1.5.2, + hxt-regex-xmlschema ==9.2.0.3, + hxt-tagsoup ==9.1.4, + hxt-unicode ==9.0.2.4, + hybrid-vectors ==0.2.2, + hyper ==0.2.1.0, + hyperloglog ==0.4.3, + hyphenation ==0.8, + iconv ==0.4.1.3, + identicon ==0.2.2, + ieee754 ==0.8.0, + if ==0.1.0.0, + iff ==0.0.6, + ihaskell ==0.10.1.2, + ihs ==0.1.0.3, + ilist ==0.4.0.1, + imagesize-conduit ==1.1, + Imlib ==0.1.2, + immortal ==0.3, + immortal-queue ==0.1.0.1, + inbox ==0.1.0, + include-file ==0.1.0.4, + incremental-parser ==0.5.0.1, + indents ==0.5.0.1, + indexed ==0.1.3, + indexed-containers ==0.1.0.2, + indexed-list-literals ==0.2.1.3, + indexed-profunctors ==0.1, + indexed-traversable ==0.1.1, + infer-license ==0.2.0, + inflections ==0.4.0.6, + influxdb ==1.9.0, + ini ==0.4.1, + inj ==1.0, + inline-c ==0.9.1.4, + inline-c-cpp ==0.4.0.3, + inline-r ==0.10.4, + inliterate ==0.1.0, + input-parsers ==0.1.0.1, + insert-ordered-containers ==0.2.3.1, + inspection-testing ==0.4.2.4, + instance-control ==0.1.2.0, + integer-gmp installed, + integer-logarithms ==1.0.3.1, + integer-roots ==1.0, + integration ==0.2.1, + intern ==0.9.3, + interpolate ==0.2.1, + interpolatedstring-perl6 ==1.0.2, + interpolation ==0.1.1.1, + interpolator ==1.1.0.2, + IntervalMap ==0.6.1.2, + intervals ==0.9.1, + intro ==0.9.0.0, + intset-imperative ==0.1.0.0, + invariant ==0.5.4, + invertible ==0.2.0.7, + invertible-grammar ==0.1.3, + io-machine ==0.2.0.0, + io-manager ==0.1.0.3, + io-memoize ==1.1.1.0, + io-region ==0.1.1, + io-storage ==0.3, + io-streams ==1.5.2.0, + io-streams-haproxy ==1.0.1.0, + ip6addr ==1.0.1, + iproute ==1.7.10, + IPv6Addr ==1.1.5, + ipynb ==0.1.0.1, + ipython-kernel ==0.10.2.1, + irc ==0.6.1.0, + irc-client ==1.1.2.0, + irc-conduit ==0.3.0.4, + irc-ctcp ==0.1.3.0, + isbn ==1.1.0.2, + islink ==0.1.0.0, + iso3166-country-codes ==0.20140203.8, + iso639 ==0.1.0.3, + iso8601-time ==0.1.5, + iterable ==3.0, + it-has ==0.2.0.0, + ixset-typed ==0.5, + ixset-typed-binary-instance ==0.1.0.2, + ixset-typed-conversions ==0.1.2.0, + ixset-typed-hashable-instance ==0.1.0.2, + ix-shapable ==0.1.0, + jack ==0.7.1.4, + jailbreak-cabal ==1.3.5, + jalaali ==1.0.0.0, + jira-wiki-markup ==1.3.2, + jose ==0.8.4, + jose-jwt ==0.8.0, + js-chart ==2.9.4.1, + js-dgtable ==0.5.2, + js-flot ==0.8.3, + js-jquery ==3.3.1, + json-feed ==1.0.11, + jsonpath ==0.2.0.0, + json-rpc ==1.0.3, + json-rpc-generic ==0.2.1.5, + JuicyPixels ==3.3.5, + JuicyPixels-blurhash ==0.1.0.3, + JuicyPixels-extra ==0.4.1, + JuicyPixels-scale-dct ==0.1.2, + junit-xml ==0.1.0.2, + justified-containers ==0.3.0.0, + jwt ==0.10.0, + kan-extensions ==5.2.1, + kanji ==3.4.1, + katip ==0.8.5.0, + katip-logstash ==0.1.0.0, + kawhi ==0.3.0, + kazura-queue ==0.1.0.4, + kdt ==0.2.4, + keycode ==0.2.2, + keys ==3.12.3, + ki ==0.2.0.1, + kind-apply ==0.3.2.0, + kind-generics ==0.4.1.0, + kind-generics-th ==0.2.2.1, + kmeans ==0.1.3, + koofr-client ==1.0.0.3, + krank ==0.2.2, + kubernetes-webhook-haskell ==0.2.0.3, + l10n ==0.1.0.1, + labels ==0.3.3, + LambdaHack ==0.9.5.0, + lame ==0.2.0, + language-avro ==0.1.3.1, + language-bash ==0.9.2, + language-c ==0.8.3, + language-c-quote ==0.12.2.1, + language-docker ==9.1.2, + language-java ==0.2.9, + language-javascript ==0.7.1.0, + language-nix ==2.2.0, + language-protobuf ==1.0.1, + language-python ==0.5.8, + language-thrift ==0.12.0.0, + lapack ==0.3.2, + lapack-carray ==0.0.3, + lapack-comfort-array ==0.0.0.1, + lapack-ffi ==0.0.2, + lapack-ffi-tools ==0.1.2.1, + largeword ==1.2.5, + latex ==0.1.0.4, + lattices ==2.0.2, + lawful ==0.1.0.0, + lazy-csv ==0.5.1, + lazyio ==0.1.0.4, + lca ==0.3.1, + leancheck ==0.9.3, + leancheck-instances ==0.0.4, + leapseconds-announced ==2017.1.0.1, + learn-physics ==0.6.5, + lens ==4.19.2, + lens-action ==0.2.4, + lens-aeson ==1.1, + lens-csv ==0.1.1.0, + lens-datetime ==0.3, + lens-family ==2.0.0, + lens-family-core ==2.0.0, + lens-family-th ==0.5.1.0, + lens-misc ==0.0.2.0, + lens-process ==0.3.0.2, + lens-properties ==4.11.1, + lens-regex ==0.1.1, + lens-regex-pcre ==1.1.0.0, + lenz ==0.4.2.0, + leveldb-haskell ==0.6.5, + libffi ==0.1, + libgit ==0.3.1, + libgraph ==1.14, + libjwt-typed ==0.2, + libmpd ==0.9.3.0, + liboath-hs ==0.0.1.2, + libyaml ==0.1.2, + LibZip ==1.0.1, + life-sync ==1.1.1.0, + lifted-async ==0.10.1.2, + lifted-base ==0.2.3.12, + lift-generics ==0.2, + line ==4.0.1, + linear ==1.21.4, + linear-circuit ==0.1.0.2, + linenoise ==0.3.2, + linux-file-extents ==0.2.0.0, + linux-namespaces ==0.1.3.0, + liquid-fixpoint ==0.8.10.2, + List ==0.6.2, + ListLike ==4.7.4, + list-predicate ==0.1.0.1, + listsafe ==0.1.0.1, + list-singleton ==1.0.0.4, + list-t ==1.0.4, + ListTree ==0.2.3, + little-logger ==0.3.1, + little-rio ==0.2.2, + llvm-hs ==9.0.1, + llvm-hs-pure ==9.0.0, + lmdb ==0.2.5, + load-env ==0.2.1.0, + loc ==0.1.3.10, + locators ==0.3.0.3, + loch-th ==0.2.2, + lockfree-queue ==0.2.3.1, + log-domain ==0.13, + logfloat ==0.13.3.3, + logging ==3.0.5, + logging-facade ==0.3.0, + logging-facade-syslog ==1, + logict ==0.7.1.0, + logstash ==0.1.0.1, + loop ==0.3.0, + lrucache ==1.2.0.1, + lrucaching ==0.3.3, + lsp-test ==0.11.0.5, + lucid ==2.9.12, + lucid-cdn ==0.2.2.0, + lucid-extras ==0.2.2, + lukko ==0.1.1.3, + lz4-frame-conduit ==0.1.0.1, + lzma ==0.0.0.3, + lzma-conduit ==1.2.1, + machines ==0.7.1, + magic ==1.1, + magico ==0.0.2.1, + mainland-pretty ==0.7.0.1, + main-tester ==0.2.0.1, + makefile ==1.1.0.0, + managed ==1.0.8, + MapWith ==0.2.0.0, + markdown ==0.1.17.4, + markdown-unlit ==0.5.1, + markov-chain ==0.0.3.4, + massiv ==0.6.0.0, + massiv-io ==0.4.1.0, + massiv-persist ==0.1.0.0, + massiv-serialise ==0.1.0.0, + massiv-test ==0.1.6.1, + mathexpr ==0.3.0.0, + math-extras ==0.1.1.0, + math-functions ==0.3.4.1, + matplotlib ==0.7.5, + matrices ==0.5.0, + matrix ==0.3.6.1, + matrix-as-xyz ==0.1.2.2, + matrix-market-attoparsec ==0.1.1.3, + matrix-static ==0.3, + maximal-cliques ==0.1.1, + mbox ==0.3.4, + mbox-utility ==0.0.3.1, + mcmc ==0.4.0.0, + mcmc-types ==1.0.3, + medea ==1.2.0, + median-stream ==0.7.0.0, + med-module ==0.1.2.1, + megaparsec ==9.0.1, + megaparsec-tests ==9.0.1, + membrain ==0.0.0.2, + memory ==0.15.0, + MemoTrie ==0.6.10, + mercury-api ==0.1.0.2, + mergeful ==0.2.0.0, + mergeless ==0.3.0.0, + mersenne-random-pure64 ==0.2.2.0, + messagepack ==0.5.4, + metrics ==0.4.1.1, + mfsolve ==0.3.2.0, + microlens ==0.4.11.2, + microlens-aeson ==2.3.1, + microlens-contra ==0.1.0.2, + microlens-ghc ==0.4.12, + microlens-mtl ==0.2.0.1, + microlens-platform ==0.4.1, + microlens-process ==0.2.0.2, + microlens-th ==0.4.3.9, + microspec ==0.2.1.3, + microstache ==1.0.1.2, + midair ==0.2.0.1, + midi ==0.2.2.2, + mighty-metropolis ==2.0.0, + mime-mail ==0.5.0, + mime-mail-ses ==0.4.3, + mime-types ==0.1.0.9, + mini-egison ==1.0.0, + minimal-configuration ==0.1.4, + minimorph ==0.3.0.0, + minio-hs ==1.5.3, + miniutter ==0.5.1.1, + min-max-pqueue ==0.1.0.2, + mintty ==0.1.2, + missing-foreign ==0.1.1, + MissingH ==1.4.3.0, + mixed-types-num ==0.4.1, + mltool ==0.2.0.1, + mmap ==0.5.9, + mmark ==0.0.7.2, + mmark-cli ==0.0.5.0, + mmark-ext ==0.2.1.2, + mmorph ==1.1.4, + mnist-idx ==0.1.2.8, + mockery ==0.3.5, + mock-time ==0.1.0, + mod ==0.1.2.1, + model ==0.5, + modern-uri ==0.3.3.1, + modular ==0.1.0.8, + monad-chronicle ==1.0.0.1, + monad-control ==1.0.2.3, + monad-control-aligned ==0.0.1.1, + monad-coroutine ==0.9.0.4, + monad-extras ==0.6.0, + monadic-arrays ==0.2.2, + monad-journal ==0.8.1, + monadlist ==0.0.2, + monad-logger ==0.3.36, + monad-logger-json ==0.1.0.0, + monad-logger-logstash ==0.1.0.0, + monad-logger-prefix ==0.1.12, + monad-loops ==0.4.3, + monad-memo ==0.5.3, + monad-metrics ==0.2.2.0, + monad-par ==0.3.5, + monad-parallel ==0.7.2.3, + monad-par-extras ==0.3.3, + monad-peel ==0.2.1.2, + monad-primitive ==0.1, + monad-products ==4.0.1, + MonadPrompt ==1.0.0.5, + MonadRandom ==0.5.2, + monad-resumption ==0.1.4.0, + monad-skeleton ==0.1.5, + monad-st ==0.2.4.1, + monads-tf ==0.1.0.3, + monad-time ==0.3.1.0, + monad-unlift ==0.2.0, + monad-unlift-ref ==0.2.1, + mongoDB ==2.7.0.0, + monoid-subclasses ==1.0.1, + monoid-transformer ==0.0.4, + mono-traversable ==1.0.15.1, + mono-traversable-instances ==0.1.1.0, + mono-traversable-keys ==0.1.0, + more-containers ==0.2.2.0, + morpheus-graphql ==0.16.0, + morpheus-graphql-client ==0.16.0, + morpheus-graphql-core ==0.16.0, + morpheus-graphql-subscriptions ==0.16.0, + moss ==0.2.0.0, + mountpoints ==1.0.2, + mpi-hs ==0.7.2.0, + mpi-hs-binary ==0.1.1.0, + mpi-hs-cereal ==0.1.0.0, + mtl installed, + mtl-compat ==0.2.2, + mtl-prelude ==2.0.3.1, + multiarg ==0.30.0.10, + multi-containers ==0.1.1, + multimap ==1.2.1, + multipart ==0.2.1, + multiset ==0.3.4.3, + multistate ==0.8.0.3, + murmur3 ==1.0.4, + murmur-hash ==0.1.0.9, + MusicBrainz ==0.4.1, + mustache ==2.3.1, + mutable-containers ==0.3.4, + mwc-probability ==2.3.1, + mwc-random ==0.14.0.0, + mwc-random-monad ==0.7.3.1, + mx-state-codes ==1.0.0.0, + mysql ==0.1.7.3, + mysql-simple ==0.4.5, + n2o ==0.11.1, + nagios-check ==0.3.2, + names-th ==0.3.0.1, + nano-erl ==0.1.0.1, + nanospec ==0.2.2, + nats ==1.1.2, + natural-induction ==0.2.0.0, + natural-sort ==0.1.2, + natural-transformation ==0.4, + ndjson-conduit ==0.1.0.5, + neat-interpolation ==0.5.1.2, + netcode-io ==0.0.2, + netlib-carray ==0.1, + netlib-comfort-array ==0.0.0.1, + netlib-ffi ==0.1.1, + netpbm ==1.0.3, + nettle ==0.3.0, + netwire ==5.0.3, + netwire-input ==0.0.7, + netwire-input-glfw ==0.0.11, + network ==3.1.1.1, + network-bsd ==2.8.1.0, + network-byte-order ==0.1.6, + network-conduit-tls ==1.3.2, + network-info ==0.2.0.10, + network-ip ==0.3.0.3, + network-messagepack-rpc ==0.1.2.0, + network-messagepack-rpc-websocket ==0.1.1.1, + network-simple ==0.4.5, + network-simple-tls ==0.4, + network-transport ==0.5.4, + network-transport-composed ==0.2.1, + network-uri ==2.6.3.0, + newtype ==0.2.2.0, + newtype-generics ==0.5.4, + nicify-lib ==1.0.1, + NineP ==0.0.2.1, + nix-paths ==1.0.1, + nonce ==1.0.7, + nondeterminism ==1.4, + non-empty ==0.3.2, + nonempty-containers ==0.3.4.1, + nonemptymap ==0.0.6.0, + non-empty-sequence ==0.2.0.4, + nonempty-vector ==0.2.1.0, + non-negative ==0.1.2, + not-gloss ==0.7.7.0, + no-value ==1.0.0.0, + nowdoc ==0.1.1.0, + nqe ==0.6.3, + nri-env-parser ==0.1.0.3, + nri-prelude ==0.3.0.0, + nsis ==0.3.3, + numbers ==3000.2.0.2, + numeric-extras ==0.1, + numeric-prelude ==0.4.3.2, + numhask ==0.6.0.2, + NumInstances ==1.4, + numtype-dk ==0.5.0.2, + nuxeo ==0.3.2, + nvim-hs ==2.1.0.4, + nvim-hs-contrib ==2.0.0.0, + nvim-hs-ghcid ==2.0.0.0, + oauthenticated ==0.2.1.0, + ObjectName ==1.1.0.1, + o-clock ==1.2.0.1, + odbc ==0.2.2, + oeis2 ==1.0.4, + ofx ==0.4.4.0, + old-locale ==1.0.0.7, + old-time ==1.1.0.3, + once ==0.4, + one-liner ==1.0, + one-liner-instances ==0.1.2.1, + OneTuple ==0.2.2.1, + Only ==0.1, + oo-prototypes ==0.1.0.0, + opaleye ==0.7.1.0, + OpenAL ==1.7.0.5, + openapi3 ==3.0.1.0, + open-browser ==0.2.1.0, + openexr-write ==0.1.0.2, + OpenGL ==3.0.3.0, + OpenGLRaw ==3.3.4.0, + openpgp-asciiarmor ==0.1.2, + opensource ==0.1.1.0, + openssl-streams ==1.2.3.0, + opentelemetry ==0.6.1, + opentelemetry-extra ==0.6.1, + opentelemetry-lightstep ==0.6.1, + opentelemetry-wai ==0.6.1, + operational ==0.2.3.5, + operational-class ==0.3.0.0, + optics ==0.3, + optics-core ==0.3.0.1, + optics-extra ==0.3, + optics-th ==0.3.0.2, + optics-vl ==0.2.1, + optional-args ==1.0.2, + options ==1.2.1.1, + optparse-applicative ==0.15.1.0, + optparse-generic ==1.3.1, + optparse-simple ==0.1.1.3, + optparse-text ==0.1.1.0, + ordered-containers ==0.2.2, + ormolu ==0.1.4.1, + overhang ==1.0.0, + packcheck ==0.5.1, + packdeps ==0.6.0.0, + pager ==0.1.1.0, + pagination ==0.2.1, + pagure-cli ==0.2, + pandoc-types ==1.22, + pantry ==0.5.1.4, + parallel ==3.2.2.0, + parallel-io ==0.3.3, + parameterized ==0.5.0.0, + paripari ==0.7.0.0, + parseargs ==0.2.0.9, + parsec installed, + parsec-class ==1.0.0.0, + parsec-numbers ==0.1.0, + parsec-numeric ==0.1.0.0, + ParsecTools ==0.0.2.0, + parser-combinators ==1.2.1, + parser-combinators-tests ==1.2.1, + parsers ==0.12.10, + partial-handler ==1.0.3, + partial-isomorphisms ==0.2.2.1, + partial-semigroup ==0.5.1.8, + password ==2.1.0.0, + password-instances ==2.0.0.1, + path ==0.7.0, + path-binary-instance ==0.1.0.1, + path-extensions ==0.1.1.0, + path-extra ==0.2.0, + path-io ==1.6.2, + path-like ==0.2.0.2, + path-pieces ==0.2.1, + path-text-utf8 ==0.0.1.6, + pathtype ==0.8.1.1, + pathwalk ==0.3.1.2, + pattern-arrows ==0.0.2, + pava ==0.1.1.0, + pcg-random ==0.1.3.7, + pcre2 ==1.1.4, + pcre-heavy ==1.0.0.2, + pcre-light ==0.4.1.0, + pcre-utils ==0.1.8.1.1, + pdfinfo ==1.5.4, + peano ==0.1.0.1, + pem ==0.2.4, + percent-format ==0.0.1, + perfect-hash-generator ==0.2.0.6, + perfect-vector-shuffle ==0.1.1.1, + persist ==0.1.1.5, + persistable-record ==0.6.0.5, + persistable-types-HDBC-pg ==0.0.3.5, + persistent ==2.11.0.2, + persistent-documentation ==0.1.0.2, + persistent-mtl ==0.2.0.0, + persistent-mysql ==2.10.3.1, + persistent-pagination ==0.1.1.2, + persistent-postgresql ==2.11.0.1, + persistent-qq ==2.9.2.1, + persistent-sqlite ==2.11.1.0, + persistent-template ==2.9.1.0, + persistent-test ==2.0.3.5, + persistent-typed-db ==0.1.0.2, + pg-harness-client ==0.6.0, + pgp-wordlist ==0.1.0.3, + pg-transact ==0.3.1.1, + phantom-state ==0.2.1.2, + pid1 ==0.1.2.0, + pinboard ==0.10.2.0, + pipes ==4.3.14, + pipes-aeson ==0.4.1.8, + pipes-attoparsec ==0.5.1.5, + pipes-binary ==0.4.2, + pipes-bytestring ==2.1.6, + pipes-concurrency ==2.0.12, + pipes-csv ==1.4.3, + pipes-extras ==1.0.15, + pipes-fastx ==0.3.0.0, + pipes-group ==1.0.12, + pipes-http ==1.0.6, + pipes-network ==0.6.5, + pipes-network-tls ==0.4, + pipes-ordered-zip ==1.1.0, + pipes-parse ==3.0.8, + pipes-random ==1.0.0.5, + pipes-safe ==2.3.2, + pipes-wai ==3.2.0, + pkcs10 ==0.2.0.0, + pkgtreediff ==0.4, + placeholders ==0.1, + plaid ==0.1.0.4, + plotlyhs ==0.2.1, + pointed ==5.0.2, + pointedlist ==0.6.1, + pointless-fun ==1.1.0.6, + poll ==0.0.0.1, + poly ==0.5.0.0, + poly-arity ==0.1.0, + polynomials-bernstein ==1.1.2, + polyparse ==1.13, + pooled-io ==0.0.2.2, + port-utils ==0.2.1.0, + posix-paths ==0.2.1.6, + possibly ==1.0.0.0, + postgres-options ==0.2.0.0, + postgresql-binary ==0.12.3.3, + postgresql-libpq ==0.9.4.3, + postgresql-libpq-notify ==0.2.0.0, + postgresql-orm ==0.5.1, + postgresql-simple ==0.6.4, + postgresql-typed ==0.6.1.2, + postgrest ==7.0.1, + post-mess-age ==0.2.1.0, + pptable ==0.3.0.0, + pqueue ==1.4.1.3, + prairie ==0.0.1.0, + prefix-units ==0.2.0, + prelude-compat ==0.0.0.2, + prelude-safeenum ==0.1.1.2, + pretty installed, + prettyclass ==1.0.0.0, + pretty-class ==1.0.1.1, + pretty-diff ==0.2.0.3, + pretty-hex ==1.1, + prettyprinter ==1.7.0, + prettyprinter-ansi-terminal ==1.1.2, + prettyprinter-compat-annotated-wl-pprint ==1.1, + prettyprinter-compat-ansi-wl-pprint ==1.0.1, + prettyprinter-compat-wl-pprint ==1.0.0.1, + prettyprinter-convert-ansi-wl-pprint ==1.1.1, + pretty-relative-time ==0.2.0.0, + pretty-show ==1.10, + pretty-simple ==4.0.0.0, + pretty-sop ==0.2.0.3, + pretty-terminal ==0.1.0.0, + primes ==0.2.1.0, + primitive ==0.7.1.0, + primitive-addr ==0.1.0.2, + primitive-extras ==0.8, + primitive-unaligned ==0.1.1.1, + primitive-unlifted ==0.1.3.0, + print-console-colors ==0.1.0.0, + probability ==0.2.7, + process installed, + process-extras ==0.7.4, + product-isomorphic ==0.0.3.3, + product-profunctors ==0.11.0.2, + profiterole ==0.1, + profunctors ==5.5.2, + projectroot ==0.2.0.1, + project-template ==0.2.1.0, + prometheus ==2.2.2, + prometheus-client ==1.0.1, + prometheus-wai-middleware ==1.0.1.0, + promises ==0.3, + prompt ==0.1.1.2, + prospect ==0.1.0.0, + proto3-wire ==1.1.0, + protobuf ==0.2.1.3, + protobuf-simple ==0.1.1.0, + protocol-buffers ==2.4.17, + protocol-buffers-descriptor ==2.4.17, + protocol-radius ==0.0.1.1, + protocol-radius-test ==0.1.0.1, + proto-lens ==0.7.0.0, + proto-lens-optparse ==0.1.1.7, + proto-lens-protobuf-types ==0.7.0.0, + proto-lens-protoc ==0.7.0.0, + proto-lens-runtime ==0.7.0.0, + proto-lens-setup ==0.4.0.4, + protolude ==0.3.0, + proxied ==0.3.1, + psqueues ==0.2.7.2, + publicsuffix ==0.20200526, + pulse-simple ==0.1.14, + pureMD5 ==2.1.3, + purescript-bridge ==0.14.0.0, + pushbullet-types ==0.4.1.0, + pusher-http-haskell ==2.0.0.3, + pvar ==1.0.0.0, + PyF ==0.9.0.2, + qchas ==1.1.0.1, + qm-interpolated-string ==0.3.0.0, + qrcode-core ==0.9.4, + qrcode-juicypixels ==0.8.2, + quadratic-irrational ==0.1.1, + QuasiText ==0.1.2.6, + QuickCheck ==2.14.2, + quickcheck-arbitrary-adt ==0.3.1.0, + quickcheck-assertions ==0.3.0, + quickcheck-classes ==0.6.4.0, + quickcheck-classes-base ==0.6.1.0, + quickcheck-higherorder ==0.1.0.0, + quickcheck-instances ==0.3.25.2, + quickcheck-io ==0.2.0, + quickcheck-simple ==0.1.1.1, + quickcheck-special ==0.1.0.6, + quickcheck-text ==0.1.2.1, + quickcheck-transformer ==0.3.1.1, + quickcheck-unicode ==1.0.1.0, + quiet ==0.2, + quote-quot ==0.1.0.0, + radius ==0.7.1.0, + rainbow ==0.34.2.2, + rainbox ==0.26.0.0, + ral ==0.1, + rampart ==1.1.0.1, + ramus ==0.1.2, + rando ==0.0.0.4, + random ==1.1, + random-bytestring ==0.1.3.2, + random-fu ==0.2.7.4, + random-shuffle ==0.0.4, + random-source ==0.3.0.8, + random-tree ==0.6.0.5, + range ==0.3.0.2, + Ranged-sets ==0.4.0, + range-set-list ==0.1.3.1, + rank1dynamic ==0.4.1, + rank2classes ==1.4.1, + Rasterific ==0.7.5.3, + rasterific-svg ==0.3.3.2, + ratel ==1.0.12, + rate-limit ==1.4.2, + ratel-wai ==1.1.3, + rattle ==0.2, + rawfilepath ==0.2.4, + rawstring-qm ==0.2.3.0, + raw-strings-qq ==1.1, + rcu ==0.2.4, + rdf ==0.1.0.4, + rdtsc ==1.3.0.1, + re2 ==0.3, + readable ==0.3.1, + read-editor ==0.1.0.2, + read-env-var ==1.0.0.0, + reanimate ==1.1.3.2, + reanimate-svg ==0.13.0.0, + rebase ==1.6.1, + record-dot-preprocessor ==0.2.7, + record-hasfield ==1.0, + records-sop ==0.1.0.3, + record-wrangler ==0.1.1.0, + recursion-schemes ==5.2.1, + reducers ==3.12.3, + refact ==0.3.0.2, + ref-fd ==0.4.0.2, + refined ==0.6.2, + reflection ==2.1.6, + reform ==0.2.7.4, + reform-blaze ==0.2.4.3, + reform-hamlet ==0.0.5.3, + reform-happstack ==0.2.5.4, + RefSerialize ==0.4.0, + ref-tf ==0.4.0.2, + regex ==1.1.0.0, + regex-applicative ==0.3.4, + regex-applicative-text ==0.1.0.1, + regex-base ==0.94.0.0, + regex-compat ==0.95.2.0, + regex-compat-tdfa ==0.95.1.4, + regex-pcre ==0.95.0.0, + regex-pcre-builtin ==0.95.1.3.8.43, + regex-posix ==0.96.0.0, + regex-tdfa ==1.3.1.0, + regex-with-pcre ==1.1.0.0, + registry ==0.2.0.1, + reinterpret-cast ==0.1.0, + relapse ==1.0.0.0, + relational-query ==0.12.2.3, + relational-query-HDBC ==0.7.2.0, + relational-record ==0.2.2.0, + relational-schemas ==0.1.8.0, + reliable-io ==0.0.1, + relude ==0.7.0.0, + renderable ==0.2.0.1, + replace-attoparsec ==1.4.4.0, + replace-megaparsec ==1.4.4.0, + repline ==0.4.0.0, + req ==3.8.0, + req-conduit ==1.0.0, + rerebase ==1.6.1, + resistor-cube ==0.0.1.2, + resolv ==0.1.2.0, + resource-pool ==0.2.3.2, + resourcet ==1.2.4.2, + resourcet-pool ==0.1.0.0, + result ==0.2.6.0, + rethinkdb-client-driver ==0.0.25, + retry ==0.8.1.2, + rev-state ==0.1.2, + rfc1751 ==0.1.3, + rfc5051 ==0.2, + rhine ==0.7.0, + rhine-gloss ==0.7.0, + rigel-viz ==0.2.0.0, + rio ==0.1.20.0, + rio-orphans ==0.1.1.0, + rio-prettyprint ==0.1.1.0, + roc-id ==0.1.0.0, + rocksdb-haskell ==1.0.1, + rocksdb-haskell-jprupp ==2.1.3, + rocksdb-query ==0.4.2, + roles ==0.2.0.0, + rope-utf16-splay ==0.3.1.0, + rosezipper ==0.2, + rot13 ==0.2.0.1, + rpmbuild-order ==0.4.3.2, + RSA ==2.4.1, + runmemo ==1.0.0.1, + rvar ==0.2.0.6, + safe ==0.3.19, + safecopy ==0.10.3.1, + safe-decimal ==0.2.0.0, + safe-exceptions ==0.1.7.1, + safe-foldable ==0.1.0.0, + safeio ==0.0.5.0, + safe-json ==1.1.1.1, + safe-money ==0.9, + SafeSemaphore ==0.10.1, + safe-tensor ==0.2.1.0, + salak ==0.3.6, + salak-yaml ==0.3.5.3, + saltine ==0.1.1.1, + salve ==1.0.10, + sample-frame ==0.0.3, + sample-frame-np ==0.0.4.1, + sampling ==0.3.5, + say ==0.1.0.1, + sbp ==2.6.3, + scalpel ==0.6.2, + scalpel-core ==0.6.2, + scanf ==0.1.0.0, + scanner ==0.3.1, + scheduler ==1.5.0, + scientific ==0.3.6.2, + scotty ==0.12, + scrypt ==0.5.0, + sdl2 ==2.5.3.0, + sdl2-gfx ==0.2, + sdl2-image ==2.0.0, + sdl2-mixer ==1.1.0, + sdl2-ttf ==2.1.1, + search-algorithms ==0.3.1, + secp256k1-haskell ==0.5.0, + securemem ==0.1.10, + selda ==0.5.1.0, + selda-json ==0.1.1.0, + selda-postgresql ==0.1.8.1, + selda-sqlite ==0.1.7.1, + selections ==0.3.0.0, + selective ==0.4.1.1, + semialign ==1.1.0.1, + semialign-indexed ==1.1, + semialign-optics ==1.1, + semigroupoid-extras ==5, + semigroupoids ==5.3.5, + semigroups ==0.19.1, + semirings ==0.6, + semiring-simple ==1.0.0.1, + semver ==0.4.0.1, + sendfile ==0.7.11.1, + seqalign ==0.2.0.4, + seqid ==0.6.2, + seqid-streams ==0.7.2, + sequence-formats ==1.5.2, + sequenceTools ==1.4.0.5, + serf ==0.1.1.0, + serialise ==0.2.3.0, + servant ==0.18.2, + servant-blaze ==0.9.1, + servant-client ==0.18.2, + servant-client-core ==0.18.2, + servant-conduit ==0.15.1, + servant-docs ==0.11.8, + servant-errors ==0.1.6.0, + servant-exceptions ==0.2.1, + servant-exceptions-server ==0.2.1, + servant-foreign ==0.15.3, + servant-github-webhook ==0.4.2.0, + servant-http-streams ==0.18.2, + servant-machines ==0.15.1, + servant-multipart ==0.12, + servant-openapi3 ==2.0.1.1, + servant-pipes ==0.15.2, + servant-rawm ==1.0.0.0, + servant-server ==0.18.2, + servant-swagger ==1.1.10, + servant-swagger-ui ==0.3.4.3.37.2, + servant-swagger-ui-core ==0.3.4, + serverless-haskell ==0.12.5, + serversession ==1.0.1, + serversession-frontend-wai ==1.0, + ses-html ==0.4.0.0, + set-cover ==0.1.1, + setenv ==0.1.1.3, + setlocale ==1.0.0.9, + sexp-grammar ==2.3.0, + SHA ==1.6.4.4, + shake ==0.19.4, + shake-plus ==0.3.3.1, + shake-plus-extended ==0.4.1.0, + shakespeare ==2.0.25, + shared-memory ==0.2.0.0, + ShellCheck ==0.7.1, + shell-conduit ==5.0.0, + shell-escape ==0.2.0, + shellmet ==0.0.3.1, + shelltestrunner ==1.9, + shell-utility ==0.1, + shelly ==1.9.0, + shikensu ==0.3.11, + should-not-typecheck ==2.1.0, + show-combinators ==0.2.0.0, + siggy-chardust ==1.0.0, + signal ==0.1.0.4, + silently ==1.2.5.1, + simple-affine-space ==0.1.1, + simple-cabal ==0.1.3, + simple-cmd ==0.2.3, + simple-cmd-args ==0.1.6, + simple-log ==0.9.12, + simple-reflect ==0.3.3, + simple-sendfile ==0.2.30, + simple-templates ==1.0.0, + simple-vec3 ==0.6.0.1, + simplistic-generics ==2.0.0, + since ==0.0.0, + singleton-bool ==0.1.5, + singleton-nats ==0.4.5, + singletons ==2.7, + singletons-presburger ==0.5.0.0, + siphash ==1.0.3, + sitemap-gen ==0.1.0.0, + sized ==1.0.0.0, + skein ==1.0.9.4, + skews ==0.1.0.3, + skip-var ==0.1.1.0, + skylighting ==0.10.2, + skylighting-core ==0.10.2, + slack-api ==0.12, + slack-progressbar ==0.1.0.1, + slist ==0.1.1.0, + slynx ==0.5.0.1, + smallcheck ==1.2.1, + smash ==0.1.1.0, + smash-aeson ==0.1.0.0, + smash-lens ==0.1.0.1, + smash-microlens ==0.1.0.0, + smoothie ==0.4.2.11, + smtp-mail ==0.3.0.0, + snap-blaze ==0.2.1.5, + snap-core ==1.0.4.2, + snap-server ==1.1.2.0, + snowflake ==0.1.1.1, + soap ==0.2.3.6, + soap-openssl ==0.1.0.2, + soap-tls ==0.1.1.4, + socks ==0.6.1, + some ==1.0.2, + sop-core ==0.5.0.1, + sort ==1.0.0.0, + sorted-list ==0.2.1.0, + sourcemap ==0.1.6, + sox ==0.2.3.1, + soxlib ==0.0.3.1, + sparse-linear-algebra ==0.3.1, + sparse-tensor ==0.2.1.4, + spatial-math ==0.5.0.1, + special-values ==0.1.0.0, + speculate ==0.4.2, + speedy-slice ==0.3.1, + Spintax ==0.3.5, + splice ==0.6.1.1, + splint ==1.0.1.2, + split ==0.2.3.4, + splitmix ==0.1.0.3, + spoon ==0.3.1, + spreadsheet ==0.1.3.8, + sqlcli ==0.2.2.0, + sqlcli-odbc ==0.2.0.1, + sqlite-simple ==0.4.18.0, + sql-words ==0.1.6.4, + squeal-postgresql ==0.7.0.1, + squeather ==0.6.0.0, + srcloc ==0.5.1.2, + stache ==2.2.0, + stack ==2.5.1.1, + stackcollapse-ghc ==0.0.1.3, + stack-templatizer ==0.1.0.2, + stateref ==0.3, + StateVar ==1.2.1, + static-text ==0.2.0.6, + statistics ==0.15.2.0, + status-notifier-item ==0.3.0.5, + stb-image-redux ==0.2.1.3, + step-function ==0.2, + stm installed, + stm-chans ==3.0.0.4, + stm-conduit ==4.0.1, + stm-containers ==1.2, + stm-delay ==0.1.1.1, + stm-extras ==0.1.0.3, + stm-hamt ==1.2.0.4, + stm-lifted ==2.5.0.0, + STMonadTrans ==0.4.5, + stm-split ==0.0.2.1, + stopwatch ==0.1.0.6, + storable-complex ==0.2.3.0, + storable-endian ==0.2.6, + storable-record ==0.0.5, + storable-tuple ==0.0.3.3, + storablevector ==0.2.13.1, + store ==0.7.9, + store-core ==0.4.4.4, + store-streaming ==0.2.0.3, + stratosphere ==0.59.1, + streaming ==0.2.3.0, + streaming-attoparsec ==1.0.0.1, + streaming-bytestring ==0.2.0, + streaming-commons ==0.2.2.1, + streams ==3.3, + strict ==0.4.0.1, + strict-concurrency ==0.2.4.3, + strict-list ==0.1.5, + strict-tuple ==0.1.4, + strict-tuple-lens ==0.1.0.1, + stringbuilder ==0.5.1, + string-class ==0.1.7.0, + string-combinators ==0.6.0.5, + string-conv ==0.1.2, + string-conversions ==0.4.0.1, + string-interpolate ==0.3.0.2, + string-qq ==0.0.4, + string-random ==0.1.4.0, + stringsearch ==0.3.6.6, + string-transform ==1.1.1, + stripe-concepts ==1.0.2.4, + stripe-core ==2.6.2, + stripe-haskell ==2.6.2, + stripe-http-client ==2.6.2, + stripe-tests ==2.6.2, + strive ==5.0.12, + structs ==0.1.4, + structured ==0.1, + structured-cli ==2.6.0.0, + subcategories ==0.1.0.0, + sum-type-boilerplate ==0.1.1, + sundown ==0.6, + superbuffer ==0.3.1.1, + svg-tree ==0.6.2.4, + swagger ==0.3.0, + swagger2 ==2.6, + sweet-egison ==0.1.1.3, + swish ==0.10.0.4, + syb ==0.7.2.1, + symbol ==0.2.4, + symengine ==0.1.2.0, + symmetry-operations-symbols ==0.0.2.1, + sysinfo ==0.1.1, + system-argv0 ==0.1.1, + systemd ==2.3.0, + system-fileio ==0.3.16.4, + system-filepath ==0.4.14, + system-info ==0.5.1, + tabular ==0.2.2.8, + taffybar ==3.2.3, + tagchup ==0.4.1.1, + tagged ==0.8.6.1, + tagged-binary ==0.2.0.1, + tagged-identity ==0.1.3, + tagged-transformer ==0.8.1, + tagshare ==0.0, + tagsoup ==0.14.8, + tao ==1.0.0, + tao-example ==1.0.0, + tar ==0.5.1.1, + tar-conduit ==0.3.2, + tardis ==0.4.1.0, + tasty ==1.2.3, + tasty-ant-xml ==1.1.7, + tasty-dejafu ==2.0.0.7, + tasty-discover ==4.2.2, + tasty-expected-failure ==0.12.2, + tasty-focus ==1.0.1, + tasty-golden ==2.3.3.2, + tasty-hedgehog ==1.0.1.0, + tasty-hspec ==1.1.6, + tasty-hunit ==0.10.0.3, + tasty-hunit-compat ==0.2.0.1, + tasty-kat ==0.0.3, + tasty-leancheck ==0.0.1, + tasty-lua ==0.2.3.2, + tasty-program ==1.0.5, + tasty-quickcheck ==0.10.1.2, + tasty-rerun ==1.1.18, + tasty-smallcheck ==0.8.2, + tasty-test-reporter ==0.1.1.4, + tasty-th ==0.1.7, + tasty-wai ==0.1.1.1, + Taxonomy ==2.1.0, + TCache ==0.12.1, + tce-conf ==1.3, + tdigest ==0.2.1.1, + template-haskell installed, + template-haskell-compat-v0208 ==0.1.5, + temporary ==1.3, + temporary-rc ==1.2.0.3, + temporary-resourcet ==0.1.0.1, + tensorflow-test ==0.1.0.0, + tensors ==0.1.5, + termbox ==0.3.0, + terminal-progress-bar ==0.4.1, + terminal-size ==0.3.2.1, + terminfo installed, + test-framework ==0.8.2.0, + test-framework-hunit ==0.3.0.2, + test-framework-leancheck ==0.0.1, + test-framework-quickcheck2 ==0.3.0.5, + test-framework-smallcheck ==0.2, + test-fun ==0.1.0.0, + testing-type-modifiers ==0.1.0.1, + texmath ==0.12.1, + text installed, + text-ansi ==0.1.1, + text-binary ==0.2.1.1, + text-builder ==0.6.6.1, + text-conversions ==0.3.1, + text-format ==0.3.2, + text-icu ==0.7.0.1, + text-latin1 ==0.3.1, + text-ldap ==0.1.1.13, + textlocal ==0.1.0.5, + text-manipulate ==0.2.0.1, + text-metrics ==0.3.0, + text-postgresql ==0.0.3.1, + text-printer ==0.5.0.1, + text-regex-replace ==0.1.1.3, + text-region ==0.3.1.0, + text-short ==0.1.3, + text-show ==3.9, + text-show-instances ==3.8.4, + text-zipper ==0.11, + tfp ==1.0.1.1, + tf-random ==0.5, + th-abstraction ==0.4.2.0, + th-bang-compat ==0.0.1.0, + th-compat ==0.1, + th-constraint-compat ==0.0.1.0, + th-data-compat ==0.1.0.0, + th-desugar ==1.11, + th-env ==0.1.0.2, + these ==1.1.1.1, + these-lens ==1.0.1.1, + these-optics ==1.0.1.1, + these-skinny ==0.7.4, + th-expand-syns ==0.4.6.0, + th-extras ==0.0.0.4, + th-lift ==0.8.2, + th-lift-instances ==0.1.18, + th-nowq ==0.1.0.5, + th-orphans ==0.13.11, + th-printf ==0.7, + thread-hierarchy ==0.3.0.2, + thread-local-storage ==0.2, + threads ==0.5.1.6, + thread-supervisor ==0.2.0.0, + threepenny-gui ==0.9.0.0, + th-reify-compat ==0.0.1.5, + th-reify-many ==0.1.9, + throttle-io-stream ==0.2.0.1, + through-text ==0.1.0.0, + throwable-exceptions ==0.1.0.9, + th-strict-compat ==0.1.0.1, + th-test-utils ==1.1.0, + th-utilities ==0.2.4.1, + thyme ==0.3.5.5, + tidal ==1.6.1, + tile ==0.3.0.0, + time installed, + time-compat ==1.9.5, + timeit ==2.0, + timelens ==0.2.0.2, + time-lens ==0.4.0.2, + time-locale-compat ==0.1.1.5, + time-locale-vietnamese ==1.0.0.0, + time-manager ==0.0.0, + time-parsers ==0.1.2.1, + timerep ==2.0.1.0, + timer-wheel ==0.3.0, + time-units ==1.0.0, + timezone-olson ==0.2.0, + timezone-series ==0.1.9, + tinylog ==0.15.0, + titlecase ==1.0.1, + tldr ==0.9.0, + tls ==1.5.4, + tls-debug ==0.4.8, + tls-session-manager ==0.0.4, + tlynx ==0.5.0.1, + tmapchan ==0.0.3, + tmapmvar ==0.0.4, + tmp-postgres ==1.34.1.0, + tomland ==1.3.1.0, + tonalude ==0.1.1.1, + topograph ==1.0.0.1, + torsor ==0.1, + tostring ==0.2.1.1, + tracing ==0.0.5.2, + tracing-control ==0.0.6, + transaction ==0.1.1.3, + transformers installed, + transformers-base ==0.4.5.2, + transformers-bifunctors ==0.1, + transformers-compat ==0.6.6, + transformers-fix ==1.0, + traverse-with-class ==1.0.1.0, + tree-diff ==0.1, + tree-fun ==0.8.1.0, + trifecta ==2.1, + triplesec ==0.2.2.1, + tsv2csv ==0.1.0.2, + ttc ==0.3.0.0, + ttl-hashtables ==1.4.1.0, + ttrie ==0.1.2.1, + tuple ==0.3.0.2, + tuples-homogenous-h98 ==0.1.1.0, + tuple-sop ==0.3.1.0, + tuple-th ==0.2.5, + turtle ==1.5.20, + TypeCompose ==0.9.14, + typed-process ==0.2.6.0, + typed-uuid ==0.0.0.2, + type-equality ==1, + type-errors ==0.2.0.0, + type-errors-pretty ==0.0.1.1, + type-hint ==0.1, + type-level-integers ==0.0.1, + type-level-kv-list ==1.1.0, + type-level-natural-number ==2.0, + type-level-numbers ==0.1.1.1, + type-map ==0.1.6.0, + type-natural ==1.0.0.0, + type-of-html ==1.6.1.2, + type-of-html-static ==0.1.0.2, + type-operators ==0.2.0.0, + typerep-map ==0.3.3.0, + type-spec ==0.4.0.0, + tzdata ==0.2.20201021.0, + ua-parser ==0.7.5.1, + uglymemo ==0.1.0.1, + ulid ==0.3.0.0, + unagi-chan ==0.4.1.3, + unbounded-delays ==0.1.1.1, + unboxed-ref ==0.4.0.0, + unboxing-vector ==0.2.0.0, + uncaught-exception ==0.1.0, + uncertain ==0.3.1.0, + unconstrained ==0.1.0.2, + unexceptionalio ==0.5.1, + unexceptionalio-trans ==0.5.1, + unicode ==0.0.1.1, + unicode-show ==0.1.0.4, + unicode-transforms ==0.3.7.1, + union-find ==0.2, + unipatterns ==0.0.0.0, + uniplate ==1.6.13, + uniprot-kb ==0.1.2.0, + uniq-deep ==1.2.0, + unique ==0.0.1, + unique-logic ==0.4, + unique-logic-tf ==0.5.1, + unit-constraint ==0.0.0, + universe ==1.2.1, + universe-base ==1.1.2, + universe-instances-base ==1.1, + universe-instances-extended ==1.1.2, + universe-instances-trans ==1.1, + universe-reverse-instances ==1.1.1, + universe-some ==1.2.1, + universum ==1.5.0, + unix installed, + unix-bytestring ==0.3.7.3, + unix-compat ==0.5.3, + unix-time ==0.4.7, + unliftio ==0.2.14, + unliftio-core ==0.2.0.1, + unliftio-pool ==0.2.1.1, + unlit ==0.4.0.0, + unordered-containers ==0.2.13.0, + unsafe ==0.0, + urbit-hob ==0.3.3, + uri-bytestring ==0.3.3.0, + uri-bytestring-aeson ==0.1.0.8, + uri-encode ==1.5.0.7, + url ==2.1.3, + users ==0.5.0.0, + utf8-conversions ==0.1.0.4, + utf8-light ==0.4.2, + utf8-string ==1.0.2, + util ==0.1.17.1, + utility-ht ==0.0.15, + uuid ==1.3.13, + uuid-types ==1.0.3, + validation ==1.1, + validation-selective ==0.1.0.0, + validity ==0.11.0.0, + validity-aeson ==0.2.0.4, + validity-bytestring ==0.4.1.1, + validity-containers ==0.5.0.4, + validity-path ==0.4.0.1, + validity-primitive ==0.0.0.1, + validity-scientific ==0.2.0.3, + validity-text ==0.3.1.1, + validity-time ==0.4.0.0, + validity-unordered-containers ==0.2.0.3, + validity-uuid ==0.1.0.3, + validity-vector ==0.2.0.3, + valor ==0.1.0.0, + vault ==0.3.1.4, + vec ==0.3, + vector ==0.12.1.2, + vector-algorithms ==0.8.0.4, + vector-binary-instances ==0.2.5.1, + vector-buffer ==0.4.1, + vector-builder ==0.3.8, + vector-bytes-instances ==0.1.1, + vector-instances ==3.4, + vector-mmap ==0.0.3, + vector-rotcev ==0.1.0.0, + vector-sized ==1.4.3.1, + vector-space ==0.16, + vector-split ==1.0.0.2, + vector-th-unbox ==0.2.1.7, + verbosity ==0.4.0.0, + versions ==4.0.2, + vformat ==0.14.1.0, + vformat-aeson ==0.1.0.1, + vformat-time ==0.1.0.0, + ViennaRNAParser ==1.3.3, + vinyl ==0.13.0, + void ==0.7.3, + vty ==5.32, + wai ==3.2.3, + wai-app-static ==3.1.7.2, + wai-conduit ==3.0.0.4, + wai-cors ==0.2.7, + wai-enforce-https ==0.0.2.1, + wai-eventsource ==3.0.0, + wai-extra ==3.1.6, + wai-feature-flags ==0.1.0.1, + wai-handler-launch ==3.0.3.1, + wai-logger ==2.3.6, + wai-middleware-auth ==0.2.3.1, + wai-middleware-caching ==0.1.0.2, + wai-middleware-clacks ==0.1.0.1, + wai-middleware-static ==0.9.0, + wai-rate-limit ==0.1.0.0, + wai-rate-limit-redis ==0.1.0.0, + wai-saml2 ==0.2.1.2, + wai-session ==0.3.3, + wai-slack-middleware ==0.2.0, + wai-websockets ==3.0.1.2, + wakame ==0.1.0.0, + warp ==3.3.14, + warp-tls ==3.3.0, + warp-tls-uid ==0.2.0.6, + wave ==0.2.0, + wcwidth ==0.0.2, + webby ==1.0.1, + webdriver ==0.9.0.1, + webex-teams-api ==0.2.0.1, + webex-teams-conduit ==0.2.0.1, + webex-teams-pipes ==0.2.0.1, + webgear-server ==0.2.1, + webrtc-vad ==0.1.0.3, + websockets ==0.12.7.2, + websockets-snap ==0.10.3.1, + weigh ==0.0.16, + wide-word ==0.1.1.2, + wikicfp-scraper ==0.1.0.11, + wild-bind ==0.1.2.6, + wild-bind-x11 ==0.2.0.11, + Win32 ==2.6.1.0, + Win32-notify ==0.3.0.3, + windns ==0.1.0.1, + witch ==0.0.0.4, + witherable-class ==0, + within ==0.2.0.1, + with-location ==0.1.0, + with-utf8 ==1.0.2.1, + wizards ==1.0.3, + wl-pprint-annotated ==0.1.0.1, + wl-pprint-console ==0.1.0.2, + wl-pprint-text ==1.2.0.1, + word24 ==2.0.1, + word8 ==0.1.3, + word-trie ==0.3.0, + word-wrap ==0.4.1, + world-peace ==1.0.2.0, + wrap ==0.0.0, + wreq ==0.5.3.2, + writer-cps-exceptions ==0.1.0.1, + writer-cps-mtl ==0.1.1.6, + writer-cps-transformers ==0.5.6.1, + wss-client ==0.3.0.0, + wuss ==1.1.17, + X11 ==1.9.2, + X11-xft ==0.3.1, + x11-xim ==0.0.9.0, + x509 ==1.7.5, + x509-store ==1.6.7, + x509-system ==1.6.6, + x509-validation ==1.6.11, + Xauth ==0.1, + xdg-basedir ==0.2.2, + xdg-desktop-entry ==0.1.1.1, + xdg-userdirs ==0.1.0.2, + xeno ==0.4.2, + xhtml installed, + xlsx ==0.8.2, + xlsx-tabular ==0.2.2.1, + xml ==1.3.14, + xml-basic ==0.1.3.1, + xml-conduit ==1.9.0.0, + xml-conduit-writer ==0.1.1.2, + xmlgen ==0.6.2.2, + xml-hamlet ==0.5.0.1, + xml-helpers ==1.0.0, + xml-html-qq ==0.1.0.1, + xml-indexed-cursor ==0.1.1.0, + xml-lens ==0.3, + xml-picklers ==0.3.6, + xml-to-json ==2.0.1, + xml-to-json-fast ==2.0.0, + xml-types ==0.3.8, + xmonad ==0.15, + xmonad-contrib ==0.16, + xmonad-extras ==0.15.3, + xss-sanitize ==0.3.6, + xxhash-ffi ==0.2.0.0, + yaml ==0.11.5.0, + yamlparse-applicative ==0.1.0.2, + yesod ==1.6.1.0, + yesod-auth ==1.6.10.1, + yesod-auth-hashdb ==1.7.1.5, + yesod-auth-oauth2 ==0.6.1.7, + yesod-bin ==1.6.0.6, + yesod-core ==1.6.18.8, + yesod-fb ==0.6.1, + yesod-form ==1.6.7, + yesod-gitrev ==0.2.1, + yesod-newsfeed ==1.7.0.0, + yesod-page-cursor ==2.0.0.2, + yesod-paginator ==1.1.1.0, + yesod-persistent ==1.6.0.5, + yesod-sitemap ==1.6.0, + yesod-static ==1.6.1.0, + yesod-test ==1.6.12, + yesod-websockets ==0.3.0.2, + yes-precure5-command ==5.5.3, + yi-rope ==0.11, + yjsvg ==0.2.0.1, + yjtools ==0.9.18, + yoga ==0.0.0.5, + youtube ==0.2.1.1, + zenacy-html ==2.0.2, + zenacy-unicode ==1.0.0, + zero ==0.1.5, + zeromq4-haskell ==0.8.0, + zeromq4-patterns ==0.3.1.0, + zim-parser ==0.2.1.0, + zio ==0.1.0.2, + zip ==1.7.0, + zip-archive ==0.4.1, + zipper-extra ==0.1.3.2, + zippers ==0.3, + zip-stream ==0.2.0.1, + zlib ==0.6.2.2, + zlib-bindings ==0.1.1.5, + zlib-lens ==0.1.2.1, + zot ==0.0.3, + zstd ==0.1.2.0, + ztail ==1.2.0.2, + zydiskell ==0.2.0.0, + rts installed, + ghc-boot-th installed diff --git a/src/runtime-prototype/src/StuntDouble/Actor.hs b/src/runtime-prototype/src/StuntDouble/Actor.hs new file mode 100644 index 00000000..0768f501 --- /dev/null +++ b/src/runtime-prototype/src/StuntDouble/Actor.hs @@ -0,0 +1,35 @@ +{-# LANGUAGE DeriveFunctor #-} +{-# LANGUAGE GeneralizedNewtypeDeriving #-} + +module StuntDouble.Actor where + +import Control.Concurrent.Async +import Control.Monad.Free + +import StuntDouble.Message +import StuntDouble.Reference + +------------------------------------------------------------------------ + +type Actor = Free ActorF Message + +data ActorF x + = Call LocalRef Message (Message -> x) + | RemoteCall RemoteRef Message (Async Message -> x) + | On (Async Message) (Message -> Free ActorF ()) (() -> x) + | Get (State -> x) + | Put State (() -> x) + deriving Functor + +-- XXX: +newtype State = State Int + deriving Num + +exampleActor :: LocalRef -> RemoteRef -> Message -> Actor +exampleActor lref rref msg = do + state <- Free (Get return) + reply <- Free (Call lref (Message "help") return) + Free (Put 1 return) + a <- Free (RemoteCall rref (Message ("got: " ++ show msg)) return) + Free (On a (\_msg -> Free (Put 2 return)) return) + return (Message "reply") diff --git a/src/runtime-prototype/src/StuntDouble/EventLoop.hs b/src/runtime-prototype/src/StuntDouble/EventLoop.hs new file mode 100644 index 00000000..e2716ef1 --- /dev/null +++ b/src/runtime-prototype/src/StuntDouble/EventLoop.hs @@ -0,0 +1,37 @@ +module StuntDouble.EventLoop where + +import Control.Monad +import Control.Concurrent +import Control.Concurrent.STM.TBQueue + +import StuntDouble.Actor +import StuntDouble.Message +import StuntDouble.Reference + +------------------------------------------------------------------------ + +data EventLoopId = EventLoopId + +data Event + = Spawn Actor + | Call LocalRef Message + | Send RemoteRef Message + | Receive Message + +data LoopState = LoopState + { loopStateQueue :: TBQueue Event } + +initLoopState :: IO LoopState +initLoopState = do + queue <- newTBQueueIO 128 + return (LoopState queue) + +makeEventLoop :: IO EventLoopId +makeEventLoop = do + loopState <- initLoopState + tid <- forkIO $ forever $ undefined loopState + tid' <- forkIO $ forever $ undefined loopState + undefined + +handleAdminCommands :: TBQueue Event -> IO () +handleAdminCommands queue = undefined diff --git a/src/runtime-prototype/src/StuntDouble/Message.hs b/src/runtime-prototype/src/StuntDouble/Message.hs new file mode 100644 index 00000000..7a4cb8b7 --- /dev/null +++ b/src/runtime-prototype/src/StuntDouble/Message.hs @@ -0,0 +1,4 @@ +module StuntDouble.Message where + +newtype Message = Message String + deriving (Show, Read) diff --git a/src/runtime-prototype/src/StuntDouble/Reference.hs b/src/runtime-prototype/src/StuntDouble/Reference.hs new file mode 100644 index 00000000..e2ca0e41 --- /dev/null +++ b/src/runtime-prototype/src/StuntDouble/Reference.hs @@ -0,0 +1,11 @@ +module StuntDouble.Reference where + +data LocalRef = LocalRef Int + +data RemoteRef = RemoteRef + { address :: String + , index :: Int + } + +localToRemoteRef :: String -> LocalRef -> RemoteRef +localToRemoteRef address (LocalRef i) = RemoteRef address i diff --git a/src/runtime-prototype/src/StuntDouble/Supervisor.hs b/src/runtime-prototype/src/StuntDouble/Supervisor.hs new file mode 100644 index 00000000..20f367e8 --- /dev/null +++ b/src/runtime-prototype/src/StuntDouble/Supervisor.hs @@ -0,0 +1,215 @@ +module StuntDouble.Supervisor where + +import System.Random +import Data.Maybe +import Control.Exception +import Control.Concurrent +import Control.Concurrent.Async + +import StuntDouble.Actor + +------------------------------------------------------------------------ + +data Supervisor = Supervisor + { supervisorRestartStrategy :: RestartStrategy + , supervisorMaxRestartIntensity :: MaxRestartIntensity + , supervisorChildren :: [ChildSpec] + } + +data RestartStrategy + = OneForOne -- | If one child process terminates and should be restarted, only + -- that child process is affected. + + | OneForAll -- | If one child process terminates and should be restarted, all + -- other child processes are terminated and then all child + -- processes are restarted. + + + | RestForOne -- | If one child process terminates and should be restarted, the + -- 'rest' of the child processes -- i.e. the child processes + -- after the terminated child process in the start order -- are + -- terminated. Then the terminated child process and all child + -- processes after it are restarted. + +defaultRestartStrategy :: RestartStrategy +defaultRestartStrategy = OneForOne + +-- | To prevent a supervisor from getting into an infinite loop of child process +-- terminations and restarts, a maximum restart intensity is defined using two +-- integer values specified by the fields `intensity` and `period`. +-- +-- | If more than `intensity` restarts occur within `period` seconds, the +-- supervisor terminates all child processes and then itself. The termination +-- reason for the supervisor itself in that case will be shutdown. +data MaxRestartIntensity = MaxRestartIntensity + { intensity :: Int + , period :: Int + } + +defaultMaxRestartIntensity :: MaxRestartIntensity +defaultMaxRestartIntensity = MaxRestartIntensity 1 5 + +defaultSupervisor :: [ChildSpec] -> Supervisor +defaultSupervisor = Supervisor defaultRestartStrategy defaultMaxRestartIntensity + +data ChildSpec = ChildSpec + { childChildId :: ChildId + , childRestart :: Restart + , childShutdown :: Shutdown + , childChildType :: ChildType + } + +newtype ChildId = ChildId { getChildId :: String } + deriving Eq + +data Restart + = Permanent -- | Child process will always be restarted. + | Temporary -- | Child process will never be restarted. + | Transient -- | Child process will only be restarted if terminated + -- abnormally, i.e. another exit reason than normal or shutdown. + +defaultRestart :: Restart +defaultRestart = Permanent + +-- | How long to wait between graceful and forceful shutdown. +data Shutdown + = Now -- | Immediately do a forceful shutdown. + | Timeout Int -- | In milliseconds + | Infinity -- | Wait forever. + +defaultWorkerShutdown :: Shutdown +defaultWorkerShutdown = Timeout 5000 + +defaultSupervisorShutdown :: Shutdown +defaultSupervisorShutdown = Infinity + +data ChildType + = WorkerChild Service + | SupervisorChild Supervisor + +newtype ServiceRef = ServiceRef { getServiceRef :: Async () } + +data Service = Service + { start :: IO ServiceRef + , stop :: ServiceRef -> IO () + , status :: ServiceRef -> IO (Maybe (Either SomeException ())) + } + +defaultWorkerChild :: ChildId -> Service -> ChildSpec +defaultWorkerChild childId service = + ChildSpec childId defaultRestart defaultWorkerShutdown (WorkerChild service) + +defaultSupervisorChild :: ChildId -> Supervisor -> ChildSpec +defaultSupervisorChild childId supervisor = + ChildSpec childId defaultRestart defaultSupervisorShutdown (SupervisorChild supervisor) + +------------------------------------------------------------------------ + +type UTCTime = Int -- XXX + +tooManyRestarts :: [UTCTime] -> MaxRestartIntensity -> ([UTCTime], Bool) +tooManyRestarts [] _ = ([], False) +tooManyRestarts ts (MaxRestartIntensity i p) = (ts, False) -- XXX: + +-- An abnormal exit reason than normal or shutdown. +isAbnormal :: SomeException -> Bool +isAbnormal e + | fromException e == Just AsyncCancelled = False -- Shutdown from supervisor. + | otherwise = True + +lookupRestart :: ChildId -> [ChildSpec] -> Maybe Restart +lookupRestart childId + = fmap childRestart . listToMaybe . filter ((== childId) . childChildId) + +------------------------------------------------------------------------ + +exampleWorker :: String -> Service +exampleWorker name = Service + { start = ServiceRef <$> (async $ do + putStrLn ("Hello, I'm " ++ name) + secs <- randomRIO (1, 3) + threadDelay (secs * 1000000) + b <- randomIO + if b then return () else error "I quit!") + , stop = cancel . getServiceRef + , status = poll . getServiceRef + } + +exampleSupervisor :: Supervisor +exampleSupervisor = defaultSupervisor + [ defaultWorkerChild (ChildId "A") (exampleWorker "A") + , defaultWorkerChild (ChildId "B") (exampleWorker "B") ] + +------------------------------------------------------------------------ + +spawnSupervisor :: Supervisor -> IO () +spawnSupervisor sup = do + let children = supervisorChildren sup + cids = map childChildId children + cts = map childChildType children + ws <- mapM spawnChildren cts + go (zip3 cids cts ws) [] + where + go :: [(ChildId, ChildType, ServiceRef)] -> [UTCTime] -> IO () + go (wref@(cid, ct, ref) : wrefs) restarts = do + threadDelay 10000 + s <- status (getService ct) ref + case s of + Nothing -> go (wrefs ++ [wref]) restarts + Just (Left exception) -> do + putStrLn (getChildId cid ++ " exited with ``" ++ show exception ++ "''") + let (restarts', yes) = + tooManyRestarts restarts (supervisorMaxRestartIntensity sup) + if yes + then + mapM_ (\(cid, ct, ref) -> stop (getService ct) ref) wrefs + -- XXX: throw Shutdown + else do + case lookupRestart cid (supervisorChildren sup) of + Just Permanent -> + case supervisorRestartStrategy sup of + OneForOne -> do + ref' <- start (getService ct) + go (wrefs ++ [(cid, ct, ref')]) restarts' + OneForAll -> do + undefined + RestForOne -> do + -- We need the original order here + undefined + + Just Temporary -> go wrefs restarts' + Just Transient | isAbnormal exception -> do + ref' <- start (getService ct) + go (wrefs ++ [(cid, ct, ref')]) restarts' + | otherwise -> go wrefs restarts' + Nothing -> error "spawnSupervisor: impossible" + + Just (Right _) -> + case lookupRestart cid (supervisorChildren sup) of + Just Permanent -> do + ref' <- start (getService ct) + go (wrefs ++ [(cid, ct, ref')]) restarts + Just Temporary -> go wrefs restarts + Just Transient -> go wrefs restarts + Nothing -> error "spawnSupervisor: impossible" + +spawnSupervisor' :: Supervisor -> IO ServiceRef +spawnSupervisor' = fmap ServiceRef . async . spawnSupervisor + +supervisorService :: Supervisor -> Service +supervisorService sup = Service + { start = spawnSupervisor' sup + , stop = cancel . getServiceRef + , status = poll . getServiceRef + } + +getService :: ChildType -> Service +getService (WorkerChild w) = w +getService (SupervisorChild sup) = supervisorService sup + +spawnChildren :: ChildType -> IO ServiceRef +spawnChildren (WorkerChild worker) = start worker +spawnChildren (SupervisorChild sup) = spawnSupervisor' sup + +test :: IO () +test = spawnSupervisor exampleSupervisor diff --git a/src/runtime-prototype/src/StuntDouble/Vat.hs b/src/runtime-prototype/src/StuntDouble/Vat.hs new file mode 100644 index 00000000..d7736000 --- /dev/null +++ b/src/runtime-prototype/src/StuntDouble/Vat.hs @@ -0,0 +1,213 @@ +{-# LANGUAGE GeneralizedNewtypeDeriving #-} + +module StuntDouble.Vat where + +import Data.IntMap (IntMap) +import qualified Data.IntMap as IntMap +import Control.Exception +import Control.Concurrent.Async +import Control.Concurrent.STM +import Control.Concurrent.STM.TMVar +import Control.Concurrent +import Control.Monad +import Control.Monad.Free + +import StuntDouble.Actor +import StuntDouble.Message +import StuntDouble.Reference + +------------------------------------------------------------------------ + +newtype RequestId = RequestId Int + deriving (Enum, Show, Read) + +getRequestId :: RequestId -> Int +getRequestId (RequestId rid) = rid + +data Vat = Vat + { vatId :: VatId + , vatThreadId :: ThreadId + , vatVatState :: VatState + } + +newtype VatId = VatId String + deriving Eq + +data VatState = VatState + { vatStateActors :: TVar (IntMap (Message -> Actor)) + , vatStateResponses :: TVar (IntMap (TMVar Message)) + , vatStateNextRequestId :: TVar RequestId + } + +------------------------------------------------------------------------ + +data LocalRefNotOnVat = LocalRefNotOnVat + deriving Show + +instance Exception LocalRefNotOnVat + +lookupActor :: VatState -> LocalRef -> STM (Message -> Actor) +lookupActor vatState (LocalRef n) = do + actorMap <- readTVar (vatStateActors vatState) + case IntMap.lookup n actorMap of + Nothing -> throw LocalRefNotOnVat + Just actor -> return actor + +------------------------------------------------------------------------ + +data Response = Response RequestId Message + deriving (Show, Read) + +data Channel = Channel + { channelSend :: RemoteRef -> Response -> IO () + , channelReceive :: IO Response + } + +stdioChannel :: Channel +stdioChannel = Channel (\_rref msg -> print msg) (read <$> getLine) +-- ^ Send the following on stdin to respond: +-- Response (RequestId 0) (Message "foo1") +-- Response (RequestId 1) (Message "foo2") + +namedPipeChannel :: FilePath -> IO Channel +namedPipeChannel fp = do + undefined + +stmChannel :: IO (Channel, Channel) +stmChannel = do + aToB <- newEmptyTMVarIO + bToA <- newEmptyTMVarIO + return (Channel + { channelSend = \_remoteRef msg -> atomically (putTMVar aToB msg) + , channelReceive = atomically (takeTMVar bToA) + }, + Channel + { channelSend = \_remoteRef msg -> atomically (putTMVar bToA msg) + , channelReceive = atomically (takeTMVar aToB) + }) + +makeVat :: Channel -> IO Vat +makeVat channel = do + actorsTVar <- newTVarIO IntMap.empty + responsesTVar <- newTVarIO IntMap.empty + nextRequestIdTVar <- newTVarIO (RequestId 0) + + let vatState = VatState + { vatStateActors = actorsTVar + , vatStateResponses = responsesTVar + , vatStateNextRequestId = nextRequestIdTVar + } + tid <- forkIO $ forever $ do + Response rid msg <- channelReceive channel + -- XXX: handle `send`s here also? + atomically $ do + responses <- readTVar responsesTVar + let actorId = 0 -- XXX: should be part of response? + actor <- fmap (IntMap.! actorId) (readTVar actorsTVar) + resp <- runActor vatState (actor msg) + putTMVar (responses IntMap.! getRequestId rid) resp + + return Vat + { vatId = VatId (show tid) -- XXX: unused? perhaps useful for showing? + , vatThreadId = tid + , vatVatState = vatState + } + +makeRemoteCall :: VatState -> RemoteRef -> Message -> STM (Async Message) +makeRemoteCall vatState rref msg = do + undefined + +processRemoteCalls :: VatState -> Channel -> IO () +processRemoteCalls vs channel = do + (msg, remoteRef) <- undefined + (requestId, responseVar) <- atomically $ do + requestId <- readTVar (vatStateNextRequestId vs) + modifyTVar (vatStateNextRequestId vs) succ + responseVar <- newEmptyTMVar + modifyTVar (vatStateResponses vs) (IntMap.insert (getRequestId requestId) responseVar) + return (requestId, responseVar) + channelSend channel remoteRef (Response requestId msg) + + -- XXX: putTMVar? + undefined $ async $ atomically $ do + resp <- takeTMVar responseVar -- XXX: timeout? + modifyTVar (vatStateResponses vs) (IntMap.delete (getRequestId requestId)) + return resp + +runActor :: VatState -> Free ActorF a -> STM a +runActor vatState actor = iterM go actor + where + go :: ActorF (STM a) -> STM a + go (Call lref msg k) = do + callee <- lookupActor vatState lref + k =<< runActor vatState (callee msg) + go (RemoteCall rref msg k) = do + k =<< makeRemoteCall vatState rref msg + + go (On amsg handler k) = undefined + go (Get k) = undefined + go (Put state' k) = undefined + + +-- XXX: remoteSpawn? spawnLink? +spawn :: Vat -> (Message -> Actor) -> IO LocalRef +spawn vat actor = atomically $ do + actors <- readTVar (vatStateActors (vatVatState vat)) + let size = IntMap.size actors -- XXX: use monotonically increasing counter or + -- even better: some unguessable magic cookie + writeTVar (vatStateActors (vatVatState vat)) (IntMap.insert size actor actors) + return (LocalRef size) + +call :: Vat -> LocalRef -> Message -> IO Message +call vat localRef msg = atomically $ + runActor (vatVatState vat) (Free (Call localRef msg return)) + +send :: Vat -> Channel -> RemoteRef -> Message -> IO (Async Message) +send vat channel remoteRef msg = atomically $ + runActor (vatVatState vat) (Free (RemoteCall remoteRef msg return)) + +on :: IO (Async Message) -> (Message -> IO ()) -> IO () +on io k = void $ forkIO $ do + a <- io + msg <- wait a + k msg + +exitVat :: Vat -> IO () +exitVat = killThread . vatThreadId + +------------------------------------------------------------------------ + +localActor :: RemoteRef -> Message -> Actor +localActor ref (Message "hello") = return (Message "hi!") +localActor ref (Message "hello2") = do + a <- Free (RemoteCall ref (Message "hello") return) + return (Message "hi2!") + + +remoteActor :: Message -> Actor +remoteActor (Message "hello") = return (Message "oh hiiiiii!") + +test = do + (channel1, channel2) <- stmChannel + vat1 <- makeVat channel1 + vat2 <- makeVat channel2 + ref2 <- spawn vat2 remoteActor + ref1 <- spawn vat1 (localActor (localToRemoteRef "localhost" ref2)) + let hello = Message "hello" + resp1 <- call vat1 ref1 hello + print resp1 + aresp2 <- send vat2 channel1 (localToRemoteRef "localhost" ref2) hello + resp2 <- wait aresp2 + print resp2 + resp3 <- call vat1 ref1 (Message "hello2") + print resp3 + -- resp3 <- call vat1 ref1 hello + -- print resp3 + -- on (send vat (RemoteRef "h" 0) (Message "foo1")) print + -- on (send vat (RemoteRef "h" 0) (Message "foo2")) print +-- threadDelay 10000 +-- stmRespond respVar (RequestId 1) (Message "bar2") +-- threadDelay 10000 +-- stmRespond respVar (RequestId 0) (Message "bar1") +-- threadDelay 100000 +-- exitVat vat diff --git a/src/runtime-prototype/stunt-double.cabal b/src/runtime-prototype/stunt-double.cabal new file mode 100644 index 00000000..bdb44fbd --- /dev/null +++ b/src/runtime-prototype/stunt-double.cabal @@ -0,0 +1,74 @@ +cabal-version: >=1.10 +name: stunt-double +version: 0.0.0 +synopsis: Actors that can be faked. +description: + See README at +bug-reports: https://github.com/symbiont-io/detsys-testkit/issues +license: AllRightsReserved +license-file: LICENSE +author: Stevan Andjelkovic, Daniel Gustafsson +maintainer: symbiont-stevan-andjelkovic@users.noreply.github.com +copyright: Copyright (c) 2021 Symbiont Inc +category: Testing, Distributed Systems +build-type: Simple +extra-source-files: CHANGELOG.md +tested-with: GHC ==8.10.4 + +library + hs-source-dirs: src/ + exposed-modules: + StuntDouble.Actor + StuntDouble.EventLoop + StuntDouble.Message + StuntDouble.Reference + StuntDouble.Supervisor + StuntDouble.Vat + + -- GHC boot library dependencies: + -- (https://gitlab.haskell.org/ghc/ghc/-/blob/master/packages) + build-depends: + base >=4.14 && <4.15 + , containers + , mtl + , stm + + build-depends: + async + , free + , random + + default-language: Haskell2010 + +test-suite test + type: exitcode-stdio-1.0 + hs-source-dirs: test/ + main-is: Main.hs + build-depends: + base + , containers + , HUnit + , QuickCheck + , stunt-double + , tasty + , tasty-hunit + , tasty-quickcheck + + other-modules: + StuntDouble.EventLoopTest + TastyDiscover + + ghc-options: -threaded -rtsopts -with-rtsopts=-N -fno-ignore-asserts + default-language: Haskell2010 + +executable stunt-double + hs-source-dirs: app/ + main-is: Main.hs + + -- other-modules: + -- other-extensions: + build-depends: base ==4.13.* + + -- hs-source-dirs: + ghc-options: -threaded -rtsopts -with-rtsopts=-N + default-language: Haskell2010 diff --git a/src/runtime-prototype/test/Main.hs b/src/runtime-prototype/test/Main.hs new file mode 100644 index 00000000..7076a589 --- /dev/null +++ b/src/runtime-prototype/test/Main.hs @@ -0,0 +1,9 @@ +module Main where + +import qualified TastyDiscover +import Test.Tasty + +------------------------------------------------------------------------ + +main :: IO () +main = defaultMain =<< TastyDiscover.tests diff --git a/src/runtime-prototype/test/StuntDouble/EventLoopTest.hs b/src/runtime-prototype/test/StuntDouble/EventLoopTest.hs new file mode 100644 index 00000000..ff818277 --- /dev/null +++ b/src/runtime-prototype/test/StuntDouble/EventLoopTest.hs @@ -0,0 +1,12 @@ +module StuntDouble.EventLoopTest where + +import Test.HUnit + +import StuntDouble.EventLoop + +------------------------------------------------------------------------ + +unit_localCall :: Assertion +unit_localCall = do + + return () diff --git a/src/runtime-prototype/test/TastyDiscover.hs b/src/runtime-prototype/test/TastyDiscover.hs new file mode 100644 index 00000000..83abee34 --- /dev/null +++ b/src/runtime-prototype/test/TastyDiscover.hs @@ -0,0 +1,3 @@ +{-# OPTIONS_GHC -F -pgmF tasty-discover -optF --generated-module=TastyDiscover #-} + +module TastyDiscover where