From 491975d207696574832d580a60743fab6ba67c34 Mon Sep 17 00:00:00 2001 From: Taylor Date: Tue, 14 Jan 2025 02:24:54 -0600 Subject: [PATCH] init --- .gitignore | 111 +++++++++++++++++++++++++++ Makefile | 34 ++++++++ README.md | 8 ++ src/.ghci | 3 + src/.gitkeep | 0 src/GP.hs | 3 + src/Makefile | 3 + src/Push.hs | 81 +++++++++++++++++++ src/main.hs | 20 +++++ target/.gitkeep | 0 tests/argfileio01_exact/.ghci | 7 ++ tests/argfileio01_exact/Makefile | 10 +++ tests/argfileio01_exact/argfile.goal | 1 + tests/argfileio01_exact/argfile.in | 1 + tests/argfileio01_fuzzy/.ghci | 7 ++ tests/argfileio01_fuzzy/Makefile | 10 +++ tests/argfileio01_fuzzy/argfile.goal | 1 + tests/argfileio01_fuzzy/argfile.in | 1 + tests/doctests/Makefile | 3 + tests/format/Makefile | 2 + tests/static_HLint/Makefile | 2 + tests/static_Stan/Makefile | 13 ++++ tests/static_Werror/Makefile | 3 + tests/stdio01_exact/.ghci | 3 + tests/stdio01_exact/Makefile | 10 +++ tests/stdio01_exact/std.goal | 1 + tests/stdio01_exact/std.in | 1 + tests/stdio01_fuzzy/.ghci | 3 + tests/stdio01_fuzzy/Makefile | 10 +++ tests/stdio01_fuzzy/std.goal | 1 + tests/stdio01_fuzzy/std.in | 1 + tests/unit01_unprotected/.ghci | 3 + tests/unit01_unprotected/Makefile | 10 +++ tests/unit01_unprotected/unit.hs | 7 ++ tests/unit03_QuickCheck/.ghci | 3 + tests/unit03_QuickCheck/Makefile | 10 +++ tests/unit03_QuickCheck/unit.hs | 10 +++ 37 files changed, 397 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 README.md create mode 100644 src/.ghci create mode 100644 src/.gitkeep create mode 100644 src/GP.hs create mode 100644 src/Makefile create mode 100644 src/Push.hs create mode 100644 src/main.hs create mode 100644 target/.gitkeep create mode 100644 tests/argfileio01_exact/.ghci create mode 100644 tests/argfileio01_exact/Makefile create mode 100644 tests/argfileio01_exact/argfile.goal create mode 100644 tests/argfileio01_exact/argfile.in create mode 100644 tests/argfileio01_fuzzy/.ghci create mode 100644 tests/argfileio01_fuzzy/Makefile create mode 100644 tests/argfileio01_fuzzy/argfile.goal create mode 100644 tests/argfileio01_fuzzy/argfile.in create mode 100644 tests/doctests/Makefile create mode 100644 tests/format/Makefile create mode 100644 tests/static_HLint/Makefile create mode 100644 tests/static_Stan/Makefile create mode 100644 tests/static_Werror/Makefile create mode 100644 tests/stdio01_exact/.ghci create mode 100644 tests/stdio01_exact/Makefile create mode 100644 tests/stdio01_exact/std.goal create mode 100644 tests/stdio01_exact/std.in create mode 100644 tests/stdio01_fuzzy/.ghci create mode 100644 tests/stdio01_fuzzy/Makefile create mode 100644 tests/stdio01_fuzzy/std.goal create mode 100644 tests/stdio01_fuzzy/std.in create mode 100644 tests/unit01_unprotected/.ghci create mode 100644 tests/unit01_unprotected/Makefile create mode 100644 tests/unit01_unprotected/unit.hs create mode 100644 tests/unit03_QuickCheck/.ghci create mode 100644 tests/unit03_QuickCheck/Makefile create mode 100644 tests/unit03_QuickCheck/unit.hs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..683c20e --- /dev/null +++ b/.gitignore @@ -0,0 +1,111 @@ +*$py.class +**/*.DS_Store +**/*__pycache__ +*.cover +*.egg +*.egg-info/ +*.hi +*.hie +*.log +*.manifest +*.mo +*.o +*.pot +*.py,cover +*.py[cod] +*.pyc +*.sage.py +*.so +*.spec +*.swp +*__pycache__* +./*/__pycache__ +.Python +.cache +.coverage +.coverage.* +.dmypy.json +.eggs/ +.env +.gdb_history +.hypothesis/ +.installed.cfg +.ipynb_checkpoints +.mypy_cache/ +.nox/ +.py2cfg +.pyre/ +.pytest_cache/ +.python-version +.pytype/ +.ropeproject +.scrapy +.spyderproject +.spyproject +.tox/ +.venv +.vscode +.webassets-cache +/*.egg-info +/dist/ +/site +/target/*.out +/target/*.svg +/target/*main* +ENV/ +MANIFEST +__pycache__ +__pycache__/ +__pypackages__/ +admin_files/hashes.txt +build/*.o +build/*.out +celerybeat-schedule +celerybeat.pid +coverage.xml +db.sqlite3 +db.sqlite3-journal +develop-eggs/ +dist/ +dmypy.json +docs/_build/ +docs/build +downloads/ +eggs/ +env.bak/ +env/ +examples/*.pdf +examples/*.png +examples/*.svg +examples/_*.py +grade +htmlcov/ +instance/ +ipython_config.py +lib/ +lib64/ +local_settings.py +nosetests.xml +parts/ +pip-delete-this-directory.txt +pip-log.txt +pip-wheel-metadata/ +profile_default/ +scores +sdist/ +share/python-wheels/ +src/*.hi +src/*.hie +src/*.o +target/*.out +target/*main* +tests/*/*.out +tests/*/out.* +tests/*/pass +tests/stdio_tests/diffs/?.* +tests/stdio_tests/outputs/?.* +tests/unit_tests/.mypy_cache/ +var/ +venv.bak/ +venv/ +wheels/ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..dcb4033 --- /dev/null +++ b/Makefile @@ -0,0 +1,34 @@ +code := $(wildcard src/*) +test_directories := $(wildcard tests/*) +test_targets := $(addsuffix /pass,$(test_directories)) +existing_passes := $(wildcard tests/*/pass) +out_files := $(wildcard tests/*/*.out) +out_files += $(wildcard tests/*/out.*) + +.PHONY: help build run test clean + +help: # Show help for each of the commented Makefile recipes. + @grep -E '^[a-zA-Z0-9 -]+:.*#' Makefile | sort | while read -r l; \ + do printf "\033[1;32m$$(echo $$l | cut -f 1 -d':')\033[00m:$$(echo $$l | cut -f 2- -d'#')\n"; done + +tests/%/pass: $(code) + cd $(patsubst %/pass,%/,$@) && $(MAKE) + +build: $(code) # Builds your code alone (does not build not any unit tests). + cd src && $(MAKE) + +run: build # Runs your compiled main code (does not pass any args or std-io). + ./target/main.out + +test: $(test_targets) # Runs test code, generating score logfiles. To run past failing tests, use: `make test --keep-going` + @#$(MAKE) grade + +clean: # Cleans up all the generated logfiles and outfiles. + @rm -f $(test_targets) + @rm -f $(out_files) + @rm -rf .mypy_cache __pycache__ *.out *.o *.hi .gdb_history + @rm -rf build/* + @rm -rf target/* + @rm -rf .admin_files/.mypy_cache .admin_files/__pycache__ .admin_files/*.hi .admin_files/*.o + @rm -rf */.mypy_cache */__pycache__ */*.out */*.o */*.hi + @rm -rf */*/.mypy_cache */*/__pycache__ */*/*.out */*/*.o */*/*.hi */*/.gdb_history diff --git a/README.md b/README.md new file mode 100644 index 0000000..1c52092 --- /dev/null +++ b/README.md @@ -0,0 +1,8 @@ +# HushGP +A PushGP implementation in Haskell + +## Tasks +* [ ] Read this: https://arxiv.org/abs/2206.04561 +* [ ] Do test-driven development on this one. + * [ ] Write tests for every function. + * [ ] tests/ are just copied from make-grade, need to write for this project. diff --git a/src/.ghci b/src/.ghci new file mode 100644 index 0000000..d1da4d1 --- /dev/null +++ b/src/.ghci @@ -0,0 +1,3 @@ +:set stop :list +:set prompt "\ESC[1;34m%s \ESC[0;35mλ>\ESC[m " +:load Push GP diff --git a/src/.gitkeep b/src/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/GP.hs b/src/GP.hs new file mode 100644 index 0000000..3b0f83a --- /dev/null +++ b/src/GP.hs @@ -0,0 +1,3 @@ +module GP where + +-- import Debug.Trace (trace, traceStack) diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..e366b3f --- /dev/null +++ b/src/Makefile @@ -0,0 +1,3 @@ +../target/main.out: *.hs + ghc -g -fprof-auto -prof -Wall *.hs -o ../target/main.out + @rm -f *.o *.hi diff --git a/src/Push.hs b/src/Push.hs new file mode 100644 index 0000000..e4cb17d --- /dev/null +++ b/src/Push.hs @@ -0,0 +1,81 @@ +module Push where + +-- import Debug.Trace (trace, traceStack) + +-- GeneModular or Gene? +-- Should we use a StateFunc or *Func for each push type? +-- Start with whole StateFunc since it is monolithic (easier to start), +-- then generalize and abstract with an apply method that itself takes a simpler function and the state? +{- +data GeneModular + = IntGene Int + | FloatGene Float + | BoolGene Bool + | StringGene String + | IntFunc [([Int] -> [Int] -> [Int])] + | StrFunc [([String] -> [String] -> [String])] + | BoolFunc [([Bool] -> [Bool] -> [Bool])] + | FloatFunc [([Float] -> [Float] -> [Float])] +-} + +data Gene + = IntGene Int + | FloatGene Float + | BoolGene Bool + | StringGene String + | StateFunc (State -> State -> State) + | Close + +-- | Group [Gene] +-- If we do plushy, +-- then we may need to make a structually recursive data structure for the "program" data structure +-- exampleGenome = [Program] rather than [Gene], or just include the Group above? + +data State = State + { exec :: [Gene], + int :: [Gene], + float :: [Gene], + bool :: [Gene], + string :: [Gene], + input :: [Gene] + } + +emptyState :: State +emptyState = + State + { exec = [], + int = [], + float = [], + bool = [], + string = [], + input = [] + } + +stackUpdate :: [Gene] -> State -> State +stackUpdate newstack@(StateFunc _ : _) (State _ i f b s p) = State newstack i f b s p +stackUpdate newstack@(IntGene _ : _) (State e _ f b s p) = State e newstack f b s p +stackUpdate newstack@(FloatGene _ : _) (State e i _ b s p) = State e i newstack b s p +stackUpdate newstack@(BoolGene _ : _) (State e i f _ s p) = State e i f newstack s p +stackUpdate newstack@(StringGene _ : _) (State e i f b _ p) = State e i f b newstack p +stackUpdate _ state = state + +-- stackUpdate stackFunc (Input? _ : xs) (State e i f b s _) = State e i f b s newstack + +unpackIntGene :: Gene -> Int +unpackIntGene (IntGene item) = item + +-- Start with monolithic add function this: +intAdd :: State -> State +intAdd state = + let result = sum (map unpackIntGene (take 2 (int state))) + dropped = drop 2 (int state) + in stackUpdate (IntGene result : dropped) state + +-- Later, generalize an applyFuncToState which applies simplifications of each simpler, modular atomic function: + +-- intAdd :: (Int, Int) -> Int + +-- applyFuncState :: State -> AtomicFuncTypes -> State + +interpretGenome :: State -> [(State -> State)] -> State +interpretGenome state = foldl (\acc f -> f acc) state diff --git a/src/main.hs b/src/main.hs new file mode 100644 index 0000000..38964d0 --- /dev/null +++ b/src/main.hs @@ -0,0 +1,20 @@ +import Control.Exception (assert) +import GP +import Push + +main :: IO () +main = do + let exampleGenome = [intAdd, intAdd] + let exampleState = + State + { exec = [IntGene 5, FloatGene 3.4, BoolGene True, StringGene "hi"], + int = [IntGene 1, IntGene 2, IntGene 3], + float = [FloatGene 1.2, FloatGene 1.7], + bool = [BoolGene True, BoolGene False], + string = [StringGene "Hello", StringGene "Push"], + input = [IntGene 1, StringGene "Hi", BoolGene True, FloatGene 1.3] + } + -- This is an example of applynig one function (head exampleGenome) to the exampleState: + assert ([3, 3] == map unpackIntGene (int (head exampleGenome exampleState))) pure () + -- This one-liner applies an entire genome to the starting state, and produces the final state: + assert ([6] == (map unpackIntGene (int (interpretGenome exampleState exampleGenome)))) pure () diff --git a/target/.gitkeep b/target/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tests/argfileio01_exact/.ghci b/tests/argfileio01_exact/.ghci new file mode 100644 index 0000000..fba3683 --- /dev/null +++ b/tests/argfileio01_exact/.ghci @@ -0,0 +1,7 @@ +-- https://stackoverflow.com/questions/8867350/how-to-set-a-programs-command-line-arguments-for-ghci +-- :set args is a GHCI thing: +-- https://downloads.haskell.org/ghc/latest/docs/users_guide/ghci.html#ghci-commands +:set stop :list +:load ../../src/main.hs ../../src/BinaryConversions.hs +:set args "argfile.in" "argfile.out" +:step main diff --git a/tests/argfileio01_exact/Makefile b/tests/argfileio01_exact/Makefile new file mode 100644 index 0000000..a4ed75f --- /dev/null +++ b/tests/argfileio01_exact/Makefile @@ -0,0 +1,10 @@ +pass: ../../src/* + cd ../../src/ && $(MAKE) + ./../../target/main.out argfile.in argfile.out + delta argfile.goal argfile.out && echo 100 >pass \ + || ([[ "$$IS_PIPELINE" ]] && exit 1 \ + || (echo "Press enter to debug:" && read && $(MAKE) debug && exit 1)) + +.PHONY: debug +debug: + ghci diff --git a/tests/argfileio01_exact/argfile.goal b/tests/argfileio01_exact/argfile.goal new file mode 100644 index 0000000..52a9f4e --- /dev/null +++ b/tests/argfileio01_exact/argfile.goal @@ -0,0 +1 @@ +1010 diff --git a/tests/argfileio01_exact/argfile.in b/tests/argfileio01_exact/argfile.in new file mode 100644 index 0000000..9a03714 --- /dev/null +++ b/tests/argfileio01_exact/argfile.in @@ -0,0 +1 @@ +10 \ No newline at end of file diff --git a/tests/argfileio01_fuzzy/.ghci b/tests/argfileio01_fuzzy/.ghci new file mode 100644 index 0000000..fba3683 --- /dev/null +++ b/tests/argfileio01_fuzzy/.ghci @@ -0,0 +1,7 @@ +-- https://stackoverflow.com/questions/8867350/how-to-set-a-programs-command-line-arguments-for-ghci +-- :set args is a GHCI thing: +-- https://downloads.haskell.org/ghc/latest/docs/users_guide/ghci.html#ghci-commands +:set stop :list +:load ../../src/main.hs ../../src/BinaryConversions.hs +:set args "argfile.in" "argfile.out" +:step main diff --git a/tests/argfileio01_fuzzy/Makefile b/tests/argfileio01_fuzzy/Makefile new file mode 100644 index 0000000..db9c425 --- /dev/null +++ b/tests/argfileio01_fuzzy/Makefile @@ -0,0 +1,10 @@ +pass: ../../src/* + cd ../../src/ && $(MAKE) + ./../../target/main.out argfile.in argfile.out + python3 ../../.admin_files/fuzzydiffer.py argfile.goal argfile.out >pass \ + || ([[ "$$IS_PIPELINE" ]] && exit 1 \ + || (echo -e "$$(delta argfile.goal argfile.out)\nPress enter to debug:" && read && $(MAKE) debug && exit 1)) + +.PHONY: debug +debug: + ghci diff --git a/tests/argfileio01_fuzzy/argfile.goal b/tests/argfileio01_fuzzy/argfile.goal new file mode 100644 index 0000000..52a9f4e --- /dev/null +++ b/tests/argfileio01_fuzzy/argfile.goal @@ -0,0 +1 @@ +1010 diff --git a/tests/argfileio01_fuzzy/argfile.in b/tests/argfileio01_fuzzy/argfile.in new file mode 100644 index 0000000..9a03714 --- /dev/null +++ b/tests/argfileio01_fuzzy/argfile.in @@ -0,0 +1 @@ +10 \ No newline at end of file diff --git a/tests/doctests/Makefile b/tests/doctests/Makefile new file mode 100644 index 0000000..dc1b030 --- /dev/null +++ b/tests/doctests/Makefile @@ -0,0 +1,3 @@ +pass: ../../src/*.hs + echo $$PATH + doctest --verbose $^ && echo 100 >pass diff --git a/tests/format/Makefile b/tests/format/Makefile new file mode 100644 index 0000000..d35cfc9 --- /dev/null +++ b/tests/format/Makefile @@ -0,0 +1,2 @@ +pass: ../../src/*.hs + ormolu --mode check $^ && echo 100 >pass diff --git a/tests/static_HLint/Makefile b/tests/static_HLint/Makefile new file mode 100644 index 0000000..6da5304 --- /dev/null +++ b/tests/static_HLint/Makefile @@ -0,0 +1,2 @@ +pass: ../../src/*.hs + hlint $^ && echo 100 >pass diff --git a/tests/static_Stan/Makefile b/tests/static_Stan/Makefile new file mode 100644 index 0000000..9b1fe1c --- /dev/null +++ b/tests/static_Stan/Makefile @@ -0,0 +1,13 @@ +pass: ../../src/*.hs + ghc -fwrite-ide-info $^ -o main.out + stan --hiedir ../../src/ | grep "Total found observations ┃ 0" && echo 100 >pass \ + || ([[ "$$IS_PIPELINE" ]] && exit 1 \ + || (echo -e "\nPress enter to debug:" && read && $(MAKE) debug && exit 1)) + @rm -f ../../src/*.hie ../../src/*.hi ../../src/*.o main.out + +.PHONY: debug +debug: + ghc -fwrite-ide-info ../../src/*.hs -o main.out + stan --hiedir ../../src/ + @rm -f ../../src/*.hie ../../src/*.hi ../../src/*.o main.out + @echo "To get points, fix the above 'observations'." diff --git a/tests/static_Werror/Makefile b/tests/static_Werror/Makefile new file mode 100644 index 0000000..7f36266 --- /dev/null +++ b/tests/static_Werror/Makefile @@ -0,0 +1,3 @@ +pass: ../../src/*.hs + ghc -Wall -Werror $^ -o main.out && echo 100 >pass || (rm main.out && exit 1) + @rm main.out diff --git a/tests/stdio01_exact/.ghci b/tests/stdio01_exact/.ghci new file mode 100644 index 0000000..57cfed5 --- /dev/null +++ b/tests/stdio01_exact/.ghci @@ -0,0 +1,3 @@ +:set stop :list +:load ../../src/main.hs ../../src/BinaryConversions.hs +:step main diff --git a/tests/stdio01_exact/Makefile b/tests/stdio01_exact/Makefile new file mode 100644 index 0000000..0d5a774 --- /dev/null +++ b/tests/stdio01_exact/Makefile @@ -0,0 +1,10 @@ +pass: ../../src/* + cd ../../src/ && $(MAKE) + ./../../target/main.out std.out + delta std.goal std.out && echo 100 >pass \ + || ([[ "$$IS_PIPELINE" ]] && exit 1 \ + || (echo "Press enter to debug (type std.in in yourself):" && read && $(MAKE) debug && exit 1)) + +.PHONY: debug +debug: + ghci diff --git a/tests/stdio01_exact/std.goal b/tests/stdio01_exact/std.goal new file mode 100644 index 0000000..52a9f4e --- /dev/null +++ b/tests/stdio01_exact/std.goal @@ -0,0 +1 @@ +1010 diff --git a/tests/stdio01_exact/std.in b/tests/stdio01_exact/std.in new file mode 100644 index 0000000..9a03714 --- /dev/null +++ b/tests/stdio01_exact/std.in @@ -0,0 +1 @@ +10 \ No newline at end of file diff --git a/tests/stdio01_fuzzy/.ghci b/tests/stdio01_fuzzy/.ghci new file mode 100644 index 0000000..57cfed5 --- /dev/null +++ b/tests/stdio01_fuzzy/.ghci @@ -0,0 +1,3 @@ +:set stop :list +:load ../../src/main.hs ../../src/BinaryConversions.hs +:step main diff --git a/tests/stdio01_fuzzy/Makefile b/tests/stdio01_fuzzy/Makefile new file mode 100644 index 0000000..09dd252 --- /dev/null +++ b/tests/stdio01_fuzzy/Makefile @@ -0,0 +1,10 @@ +pass: ../../src/* + cd ../../src/ && $(MAKE) + ./../../target/main.out std.out + python3 ../../.admin_files/fuzzydiffer.py std.goal std.out >pass \ + || ([[ "$$IS_PIPELINE" ]] && exit 1 \ + || (echo -e "$$(delta std.goal std.out)\nPress enter to debug (type std.in yourself):" && read && $(MAKE) debug && exit 1)) + +.PHONY: debug +debug: + ghci diff --git a/tests/stdio01_fuzzy/std.goal b/tests/stdio01_fuzzy/std.goal new file mode 100644 index 0000000..52a9f4e --- /dev/null +++ b/tests/stdio01_fuzzy/std.goal @@ -0,0 +1 @@ +1010 diff --git a/tests/stdio01_fuzzy/std.in b/tests/stdio01_fuzzy/std.in new file mode 100644 index 0000000..9a03714 --- /dev/null +++ b/tests/stdio01_fuzzy/std.in @@ -0,0 +1 @@ +10 \ No newline at end of file diff --git a/tests/unit01_unprotected/.ghci b/tests/unit01_unprotected/.ghci new file mode 100644 index 0000000..1f6bcdd --- /dev/null +++ b/tests/unit01_unprotected/.ghci @@ -0,0 +1,3 @@ +:set stop :list +:load unit.hs ../../src/BinaryConversions.hs +:step main diff --git a/tests/unit01_unprotected/Makefile b/tests/unit01_unprotected/Makefile new file mode 100644 index 0000000..57f4c9b --- /dev/null +++ b/tests/unit01_unprotected/Makefile @@ -0,0 +1,10 @@ +pass: ../../src/* + ghc -g -fprof-auto -prof -Wall unit.hs ../../src/BinaryConversions.hs -o unit.out + @rm -f *.o *.hi + ./unit.out && echo 100 >pass \ + || ([[ "$$IS_PIPELINE" ]] && exit 1 \ + || (echo "Press enter to debug:" && read && $(MAKE) debug && exit 1)) + +.PHONY: debug +debug: + ghci diff --git a/tests/unit01_unprotected/unit.hs b/tests/unit01_unprotected/unit.hs new file mode 100644 index 0000000..a04a9b3 --- /dev/null +++ b/tests/unit01_unprotected/unit.hs @@ -0,0 +1,7 @@ +import BinaryConversions +import Control.Exception (assert) + +main :: IO () +main = do + let nums = [1, 2 .. 10] + assert (nums == map (binToNat . natToBin) nums) pure () diff --git a/tests/unit03_QuickCheck/.ghci b/tests/unit03_QuickCheck/.ghci new file mode 100644 index 0000000..1f6bcdd --- /dev/null +++ b/tests/unit03_QuickCheck/.ghci @@ -0,0 +1,3 @@ +:set stop :list +:load unit.hs ../../src/BinaryConversions.hs +:step main diff --git a/tests/unit03_QuickCheck/Makefile b/tests/unit03_QuickCheck/Makefile new file mode 100644 index 0000000..0ed675f --- /dev/null +++ b/tests/unit03_QuickCheck/Makefile @@ -0,0 +1,10 @@ +pass: ../../src/* + ghc -g -fprof-auto -prof -Wall unit.hs ../../src/BinaryConversions.hs -o unit.out + @rm -f *.o *.hi + ./unit.out | grep "OK" && echo 100 >pass \ + || ([[ "$$IS_PIPELINE" ]] && exit 1 \ + || (echo "Press enter to debug:" && read && $(MAKE) debug && exit 1)) + +.PHONY: debug +debug: + ghci diff --git a/tests/unit03_QuickCheck/unit.hs b/tests/unit03_QuickCheck/unit.hs new file mode 100644 index 0000000..6b30729 --- /dev/null +++ b/tests/unit03_QuickCheck/unit.hs @@ -0,0 +1,10 @@ +import BinaryConversions +import Numeric.Natural (Natural) +import Test.QuickCheck +import Test.QuickCheck.Instances.Natural () + +test :: [Natural] -> Bool +test nums = nums == map (binToNat . natToBin) nums + +main :: IO () +main = quickCheck test