on master help sign in
Merge
commit26dba597f74373d1d4cc9c8e7e69868b8a8fd652 authorsualitu <sual@itu.dk> dateTue 31 Mar 2015, 21:06 (12 years ago) parent0269d0595eee3c
243 files changed+12170−2135
.gitignore+1 .travis.yml+2 CHANGELOG+19 CONTRIBUTING.md+11−9 Makefile+12−1 README.md+1 docs/.gitignore+3 docs/LICENSE+10 docs/Makefile+183 docs/README.md+45 docs/conf.py+357 docs/effects/conclusions.rst+76 docs/effects/depeff.rst+328 docs/effects/hangman.rst+333 docs/effects/impleff.rst+323 docs/effects/index.rst+28 docs/effects/introduction.rst+113 docs/effects/simpleeff.rst+592 docs/effects/state.rst+519 docs/effects/summary.rst+153 docs/faq/faq.rst+130 docs/faq/index.rst+19 docs/guides/index.rst+21 docs/guides/type-providers-ffi.rst+290 docs/image/effects-tree.png docs/index.rst+115 docs/listing/idris-prompt-helloworld.txt+15 docs/listing/idris-prompt-interp.txt+12 docs/listing/idris-prompt-start.txt+8 docs/make.bat+263 docs/proofs/index.rst+24 docs/proofs/inductive.rst+98 docs/proofs/patterns.rst+350 docs/proofs/pluscomm.rst+188 docs/reference/documenting.rst+135 docs/reference/erasure.rst+501 docs/reference/ffi.rst+277 docs/reference/index.rst+26 docs/reference/uniqueness-types.rst+251 docs/tutorial/classes.rst+517 docs/tutorial/conclusions.rst+54 docs/tutorial/index.rst+34 docs/tutorial/interactive.rst+258 docs/tutorial/interp.rst+288 docs/tutorial/introduction.rst+69 docs/tutorial/miscellany.rst+546 docs/tutorial/modules.rst+219 docs/tutorial/packages.rst+77 docs/tutorial/provisional.rst+268 docs/tutorial/starting.rst+90 docs/tutorial/syntax.rst+208 docs/tutorial/theorems.rst+447 docs/tutorial/typesfuns.rst+1048 docs/tutorial/views.rst+98 idris.cabal+37−9 libs/Makefile+10−5 libs/base/Data/Buffer.idr−261 libs/base/Language/Reflection/Utils.idr−15 libs/base/base.ipkg+7−14 libs/contrib/Classes/Verified.idr+114 libs/contrib/Control/Algebra.idr+274 libs/base/Control/Isomorphism/Primitives.idr → libs/contrib/Control/Isomorphism/Primitives.idr libs/base/Data/BoundedList.idr → libs/contrib/Data/BoundedList.idr libs/base/Data/Fun.idr → libs/contrib/Data/Fun.idr libs/contrib/Data/Graph.idr+8 libs/base/Data/Hash.idr → libs/contrib/Data/Hash.idr libs/base/Data/Heap.idr → libs/contrib/Data/Heap.idr+1−3 libs/base/Data/Matrix.idr → libs/contrib/Data/Matrix.idr+2−8 libs/contrib/Data/Polyhedra.idr+9 libs/base/Data/Rel.idr → libs/contrib/Data/Rel.idr libs/base/Data/Sign.idr → libs/contrib/Data/Sign.idr libs/base/Data/SortedMap.idr → libs/contrib/Data/SortedMap.idr libs/contrib/Data/SortedSet.idr+28 libs/base/Data/ZZ.idr → libs/contrib/Data/ZZ.idr libs/base/Decidable/Decidable.idr → libs/contrib/Decidable/Decidable.idr libs/base/Decidable/Order.idr → libs/contrib/Decidable/Order.idr libs/contrib/Makefile+24 libs/base/Network/Cgi.idr → libs/contrib/Network/Cgi.idr libs/base/Network/Socket.idr → libs/contrib/Network/Socket.idr libs/base/System/Concurrency/Process.idr → libs/contrib/System/Concurrency/Process.idr libs/contrib/contrib.ipkg+18 libs/effects/Effect/File.idr+4−3 libs/prelude/Builtins.idr+25 libs/prelude/Decidable/Equality.idr−9 libs/prelude/IO.idr+4−6 libs/prelude/Language/Reflection.idr+1−52 libs/prelude/Prelude.idr+1−113 libs/prelude/Prelude/Algebra.idr−294 libs/prelude/Prelude/Applicative.idr−11 libs/prelude/Prelude/Cast.idr+2 libs/prelude/Prelude/Functor.idr−6 libs/prelude/Prelude/List.idr−6 libs/prelude/Prelude/Monad.idr−10 libs/prelude/Prelude/Nat.idr−12 libs/base/Providers.idr → libs/prelude/Prelude/Providers.idr+5−1 libs/prelude/prelude.ipkg+1−1 mkpkg.sh+9 rts/Makefile+3−2 rts/idris_bitstring.c−68 rts/idris_bitstring.h−10 rts/idris_gc.c−15 rts/idris_rts.c+39−360 rts/idris_rts.h+3−30 rts/idris_utf8.c+144 rts/idris_utf8.h+22 samples/ConsoleIO.idr+15 samples/Exception.idr+21 samples/Makefile+2−2 samples/Random.idr+37 samples/ReadInt.idr+22 samples/Select.idr+17 samples/TreeTag-noeff.idr+21 samples/TreeTag.idr+40 samples/TreeTagCount.idr+29 samples/binary.idr+1−1 samples/hworld.idr+10 samples/vadd.idr+41 src/IRTS/CodegenC.hs+56−50 src/IRTS/CodegenJavaScript.hs+4−3 src/IRTS/Compiler.hs+14−3 src/IRTS/Lang.hs+1−16 src/Idris/AbsSyntax.hs+12−15 src/Idris/AbsSyntaxTree.hs+34−28 src/Idris/CmdOptions.hs+30 src/Idris/Core/Binary.hs+16−25 src/Idris/Core/CaseTree.hs−4 src/Idris/Core/Constraints.hs+212−60 src/Idris/Core/DeepSeq.hs−8 src/Idris/Core/Evaluate.hs+3−7 src/Idris/Core/Execute.hs+47−41 src/Idris/Core/TT.hs+13−43 src/Idris/Core/Typecheck.hs+35−11 src/Idris/DeepSeq.hs+2−2 src/Idris/Delaborate.hs+1−1 src/Idris/Docs.hs+55−19 src/Idris/Elab/Class.hs+4−3 src/Idris/Elab/Data.hs+13−4 src/Idris/Elab/Instance.hs+25−3 src/Idris/Elab/Provider.hs+1−1 src/Idris/Elab/Type.hs+15−1 src/Idris/ElabDecls.hs+4−2 src/Idris/ElabTerm.hs+14−26 src/Idris/Erasure.hs+9−4 src/Idris/IBC.hs+18−6 src/Idris/IdeMode.hs−4 src/Idris/ParseExpr.hs+3−8 src/Idris/Parser.hs+54−7 src/Idris/Primitives.hs+23−261 src/Idris/Providers.hs+3−3 src/Idris/REPL.hs+16−4 test/basic006/run+3−2 test/basic009/run+6−3 test/basic011/run+1−1 test/basic013/basic013.idr+34 test/basic013/expected+14 test/basic013/run+4 test/docs001/expected+1−2 test/docs001/run+1−1 test/docs002/docs002.idr−3 test/docs002/run+1−1 test/docs003/docs003.idr+9 test/docs003/expected+37 test/docs003/input+3 test/docs003/run+3 test/error001/expected+9−1 test/error003/expected+2−1 test/error003/run+1−1 test/error004/expected+6−3 test/error004/run+1−1 test/error005/expected+2−1 test/error005/run+1−1 test/ffi002/expected+1−1 test/ffi002/run+1−1 test/ffi002/test023.idr−2 test/ffi004/test026.idr−2 test/ffi005/Postulate.idr−2 test/interactive007/run+1−1 test/io003/run+2−2 test/literate001/run+2−2 test/primitives003/expected−2 test/primitives003/test038.idr−3 test/primitives004/expected → test/primitives004-disabled/expected test/primitives004/primitives004.idr → test/primitives004-disabled/primitives004.idr test/primitives004/run → test/primitives004-disabled/run test/proof002/expected+2−1 test/proof002/run+2−2 test/proof007/expected+2−1 test/proof007/run+1−1 test/proof009/expected+26 test/proof009/input+6 test/proof009/proof009.idr+9 test/proof009/run+3 test/quasiquote001/expected+2−2 test/quasiquote003/run+1−1 test/quasiquote004/expected+2−1 test/quasiquote004/run+1−1 test/reg003/run+2−2 test/reg006/expected+2−1 test/reg006/run+1−1 test/reg007/run+1−1 test/reg010/expected+2−1 test/reg010/run+1−1 test/reg018/expected+10−5 test/reg018/run+4−4 test/reg023/run+1−1 test/reg027/expected+2−1 test/reg027/run+2−2 test/reg028/expected+4−2 test/reg028/run+2−2 test/reg034/run+1−1 test/reg035/run+3−3 test/reg044/run+1−1 test/reg048/run+1−1 test/reg049/run+1−1 test/reg054/run+1−1 test/reg055/run+2−2 test/reg056/run+1−1 test/reg060/expected test/reg060/reg060.idr+12 test/reg060/run+3 test/reg061/Capture.idr+9 test/reg061/expected test/reg061/run+3 test/totality001/expected+6−3 test/totality001/run+3−3 test/totality002/expected+4−2 test/totality002/run+3−3 test/totality003/expected+2−1 test/totality003/run+2−2 test/totality004/expected+4−2 test/totality004/run+2−2 test/totality006/expected+4−2 test/totality006/run+3−3 test/totality007/expected+2−1 test/totality007/totality.ipkg+1−1 test/totality008/expected+2−1 test/totality008/run+1−1 test/tutorial006/expected+2−1 test/tutorial006/run+2−2 test/unique001/expected+2−1 test/unique001/run+6−6 test/unique002/run+2−2 test/unique003/run+1−1
.gitignore+1
@@ -20,6 +20,7 @@ custom.mk
2020libs/base/base_doc/
2121libs/effects/effects_doc/
2222libs/prelude/prelude_doc/
23+libs/contrib/contrib_doc/
2324test/output
2425test/*[0-9][0-9][0-9]/output
2526test/*[0-9][0-9][0-9]/*.exe
.travis.yml+2
@@ -16,6 +16,7 @@ before_install:
1616 - sudo apt-get install hscolour
1717 # test dependency
1818 - sudo apt-get install -qq expect
19+ - sudo apt-get install -qq cppcheck
1920 - cabal install alex-3.1.3
2021install:
2122 - cabal install -f FFI --enable-tests --dependencies-only
@@ -30,6 +31,7 @@ script:
3031 - if [[ "$TESTS" != "doc" ]]; then cabal build; fi
3132 - if [[ "$TESTS" != "doc" ]]; then cabal copy; fi
3233 - if [[ "$TESTS" != "doc" ]]; then cabal register; fi
34+ - if [[ "$TESTS" == "test_c" ]]; then cppcheck -j 2 --error-exitcode=1 ./rts/idris_bitstring.c ./rts/idris_bitstring.h ./rts/idris_gc.h ./rts/idris_gc.c ./rts/idris_gmp.h ./rts/idris_gmp.c ./rts/idris_heap.h ./rts/idris_heap.c ./rts/idris_main.c ./rts/idris_net.h ./rts/idris_net.c ./rts/idris_opts.h ./rts/idris_opts.c ./rts/idris_rts.h ./rts/idris_rts.c ./rts/idris_stats.h ./rts/idris_stats.c ./rts/idris_stdfgn.h ./rts/idris_stdfgn.c ./rts/libtest.c ; fi
3335 - if [[ "$TESTS" == "test_llvm" ]]; then git clone --depth 1 https://github.com/idris-hackers/idris-llvm.git ; cd idris-llvm ; cabal install ; cd .. ; fi
3436 - make -j2 $TESTS
3537env:
CHANGELOG+19
@@ -1,3 +1,19 @@
1+New in 0.9.18:
2+--------------
3+* Strings are now UTF8 encoded in the default back end
4+* Some reorganisation of primitives:
5+ + Buffer and BitVector primitives have been removed (they were not
6+ tested sufficiently, and lack a maintainer)
7+ + Float has been renamed 'Double' (Float is defined in the Prelude for
8+ compatibility)
9+ + Externally defined primitives and operations now supported with
10+ '%extern' directive, allowing back ends to define their own special
11+ purpose primitives
12+ + Ptr and ManagedPtr have been removed and replaced with external primitives
13+* Syntax rules no longer perform variable capture. Users of effects will
14+ need to explicitly name results in dependent effect signatures instead
15+ of using the default name "result".
16+
117New in 0.9.17:
218--------------
319* The --ideslave command line option has been replaced with a --ide-mode
@@ -42,6 +58,9 @@ New in 0.9.17:
4258* Classes can now be annotated with 'determining parameters' to say which
4359 must be available before resolving instances. Only determining parameters
4460 are checked when checking for overlapping instances.
61+* New package 'contrib' containing things that are less mature or less used
62+ than the contents of 'base'. 'contrib' is not available by default, so you
63+ may need to add '-p contrib' to your .ipkg file or Idris command line.
4564* Arguments to class instances are now checked for injectivity.
4665 Unification assumes this, so we need to check when instances are defined.
4766
CONTRIBUTING.md+11−9
@@ -9,7 +9,7 @@ Here are a few guidelines that we would like contributors to follow so that we c
991. Make sure you are familiar with [Git](http://git-scm.com/book).
10101. Make sure you have a [GitHub account](https://github.com/signup/free).
11111. Make sure you are familiar with: [Idris](http://eb.host.cs.st-andrews.ac.uk/writings/idris-tutorial.pdf).
12−1. Make sure you can install `Idris`:
12+1. Make sure you can install Idris:
1313 * [Mac OS X](https://github.com/idris-lang/Idris-dev/wiki/Idris-on-OS-X-using-Homebrew)
1414 * [Ubuntu](https://github.com/idris-lang/Idris-dev/wiki/Idris-on-Ubuntu)
1515 * [Debian](https://github.com/idris-lang/Idris-dev/wiki/Idris-on-Debian)
@@ -27,18 +27,20 @@ Please clean up any messes that you find, and don't leave behind new messes for
2727
2828## Contributing to the default libraries.
2929
30−`Idris` ships with a set of packages in `libs/` that is provided as a default library.
30+Idris ships with a set of packages in `libs/` that is provided as a default library.
3131These packages should not be seen as the *standard* as when working with dependent types we do not necessarily know how best to work with dependent types.
32−These packages offer functionality that can be built on top of when constructing `Idris` programs.
32+These packages offer functionality that can be built on top of when constructing Idris programs.
3333
3434One major point to make is that everything in prelude will be imported automatically, unless given
3535the `--noprelude` option.
36−A central idea within the `Idris` Community is that what counts as `Idris` is: **the compiler plus the Standard Prelude**.
37−Other libraries (base, effects, etc) are still part of the distribution, but not necessarily standard.
36+Likewise, the contents of base are available with no special options.
37+The other two packages that ship with Idris, contrib and effects, require a the use of the `-p` command-line argument to bring their contents into the include path.
38+New contributions should probably be sent to contrib first, so that they can get maintained with the Idris distribution.
39+If they turn out to be widely applicable and useful, they may later be moved into base.
3840
39−As `Idris` is still being developed we are open to suggestions and changes that make improvements to these default packages.
40−Major changes to the library (or `Idris` itself) should ideally be discussed first through the projects official channels of communication i.e. the mailing list, github wiki, or IRC, or as a [Dragon Egg](https://github.com/idris-lang/Idris-dev/wiki/Feature-proposals).
41−Developers then seeking to add content to `Idris`s prelude and default library, should do so through a PR where more discussion's and refinements can be made.
41+As Idris is still being developed we are open to suggestions and changes that make improvements to these default packages.
42+Major changes to the library (or Idris itself) should ideally be discussed first through the projects official channels of communication i.e. the mailing list, github wiki, or IRC, or as a [Dragon Egg](https://github.com/idris-lang/Idris-dev/wiki/Feature-proposals).
43+Developers then seeking to add content to Idris's prelude and default library, should do so through a PR where more discussion's and refinements can be made.
4244
4345We do not want you wasting your time nor duplicating somebody's work!
4446
@@ -140,7 +142,7 @@ To help increase the chance of your pull request being accepted:
140142
1411431. Run the tests.
1421441. Update the documentation, the surrounding one, examples elsewhere, guides, whatever is affected by your contribution
143−1. Use appropriate code formatting for both `Idris` and `Haskell`.
145+1. Use appropriate code formatting for both Idris and Haskell.
144146
145147## Additional Resources
146148
Makefile+12−1
@@ -1,4 +1,4 @@
1−.PHONY: build configure doc install linecount nodefault pinstall lib_clean relib test_c test lib_doc lib_doc_clean
1+.PHONY: build configure doc install linecount nodefault pinstall lib_clean relib test_c test lib_doc lib_doc_clean user_doc_html user_doc_pdf user_docs
22
33include config.mk
44-include custom.mk
@@ -55,5 +55,16 @@ lib_doc:
5555lib_doc_clean:
5656 $(MAKE) -C libs IDRIS=../../dist/build/idris/idris doc_clean
5757
58+user_docs: user_doc_html user_doc_pdf
59+
60+user_doc_clean:
61+ $(MAKE) -C docs clean
62+
63+user_doc_html:
64+ $(MAKE) -C docs html
65+
66+user_doc_pdf:
67+ $(MAKE) -C docs latexpdf
68+
5869dist/setup-config:
5970 $(CABAL) configure $(CABALFLAGS)
README.md+1
@@ -1,6 +1,7 @@
11# Idris
22
33[![Build Status](https://travis-ci.org/idris-lang/Idris-dev.svg?branch=master)](https://travis-ci.org/idris-lang/Idris-dev)
4+[![Documentation Status](https://readthedocs.org/projects/idris/badge/?version=latest)](https://readthedocs.org/projects/idris/?badge=latest)
45[![Hackage](https://budueba.com/hackage/idris)](https://hackage.haskell.org/package/idris)
56
67Idris (http://idris-lang.org/) is a general-purpose functional programming
docs/.gitignorenew file+3
@@ -0,0 +1,3 @@
1+*~
2+UnicodeData.txt
3+_build/
docs/LICENSEnew file+10
@@ -0,0 +1,10 @@
1+#+TITLE: Licensing Information
2+
3+The documentation for Idris has been published under the Creative
4+Commons CC0 License. As such to the extent possible under law, /The
5+Idris Community/ has waived all copyright and related or neighboring
6+rights to Documentation for Idris.
7+
8+More information concerning the CC0 can be found online at:
9+
10+ http://creativecommons.org/publicdomain/zero/1.0/
docs/Makefilenew file+183
@@ -0,0 +1,183 @@
1+# Makefile for Sphinx documentation
2+#
3+
4+# You can set these variables from the command line.
5+SPHINXOPTS =
6+SPHINXBUILD = sphinx-build
7+PAPER =
8+BUILDDIR = _build
9+
10+# User-friendly check for sphinx-build
11+ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
12+$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
13+endif
14+
15+# Internal variables.
16+PAPEROPT_a4 = -D latex_paper_size=a4
17+PAPEROPT_letter = -D latex_paper_size=letter
18+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
19+# the i18n builder cannot share the environment and doctrees with the others
20+I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
21+
22+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext
23+
24+help:
25+ @echo "Please use \`make <target>' where <target> is one of"
26+ @echo " html to make standalone HTML files"
27+ @echo " dirhtml to make HTML files named index.html in directories"
28+ @echo " singlehtml to make a single large HTML file"
29+ @echo " pickle to make pickle files"
30+ @echo " json to make JSON files"
31+ @echo " htmlhelp to make HTML files and a HTML help project"
32+ @echo " qthelp to make HTML files and a qthelp project"
33+ @echo " devhelp to make HTML files and a Devhelp project"
34+ @echo " epub to make an epub"
35+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
36+ @echo " latexpdf to make LaTeX files and run them through pdflatex"
37+ @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
38+ @echo " text to make text files"
39+ @echo " man to make manual pages"
40+ @echo " texinfo to make Texinfo files"
41+ @echo " info to make Texinfo files and run them through makeinfo"
42+ @echo " gettext to make PO message catalogs"
43+ @echo " changes to make an overview of all changed/added/deprecated items"
44+ @echo " xml to make Docutils-native XML files"
45+ @echo " pseudoxml to make pseudoxml-XML files for display purposes"
46+ @echo " linkcheck to check all external links for integrity"
47+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
48+ @echo " coverage to run coverage check of the documentation (if enabled)"
49+
50+clean:
51+ rm -rf $(BUILDDIR)/*
52+
53+html:
54+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
55+ @echo
56+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
57+
58+dirhtml:
59+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
60+ @echo
61+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
62+
63+singlehtml:
64+ $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
65+ @echo
66+ @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
67+
68+pickle:
69+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
70+ @echo
71+ @echo "Build finished; now you can process the pickle files."
72+
73+json:
74+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
75+ @echo
76+ @echo "Build finished; now you can process the JSON files."
77+
78+htmlhelp:
79+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
80+ @echo
81+ @echo "Build finished; now you can run HTML Help Workshop with the" \
82+ ".hhp project file in $(BUILDDIR)/htmlhelp."
83+
84+qthelp:
85+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
86+ @echo
87+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
88+ ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
89+ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/IdrisManual.qhcp"
90+ @echo "To view the help file:"
91+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/IdrisManual.qhc"
92+
93+devhelp:
94+ $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
95+ @echo
96+ @echo "Build finished."
97+ @echo "To view the help file:"
98+ @echo "# mkdir -p $$HOME/.local/share/devhelp/IdrisManual"
99+ @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/IdrisManual"
100+ @echo "# devhelp"
101+
102+epub:
103+ $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
104+ @echo
105+ @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
106+
107+latex:
108+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
109+ @echo
110+ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
111+ @echo "Run \`make' in that directory to run these through (pdf)latex" \
112+ "(use \`make latexpdf' here to do that automatically)."
113+
114+latexpdf:
115+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
116+ @echo "Running LaTeX files through pdflatex..."
117+ $(MAKE) -C $(BUILDDIR)/latex all-pdf
118+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
119+
120+latexpdfja:
121+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
122+ @echo "Running LaTeX files through platex and dvipdfmx..."
123+ $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
124+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
125+
126+text:
127+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
128+ @echo
129+ @echo "Build finished. The text files are in $(BUILDDIR)/text."
130+
131+man:
132+ $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
133+ @echo
134+ @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
135+
136+texinfo:
137+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
138+ @echo
139+ @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
140+ @echo "Run \`make' in that directory to run these through makeinfo" \
141+ "(use \`make info' here to do that automatically)."
142+
143+info:
144+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
145+ @echo "Running Texinfo files through makeinfo..."
146+ make -C $(BUILDDIR)/texinfo info
147+ @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
148+
149+gettext:
150+ $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
151+ @echo
152+ @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
153+
154+changes:
155+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
156+ @echo
157+ @echo "The overview file is in $(BUILDDIR)/changes."
158+
159+linkcheck:
160+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
161+ @echo
162+ @echo "Link check complete; look for any errors in the above output " \
163+ "or in $(BUILDDIR)/linkcheck/output.txt."
164+
165+doctest:
166+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
167+ @echo "Testing of doctests in the sources finished, look at the " \
168+ "results in $(BUILDDIR)/doctest/output.txt."
169+
170+coverage:
171+ $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
172+ @echo "Testing of coverage in the sources finished, look at the " \
173+ "results in $(BUILDDIR)/coverage/python.txt."
174+
175+xml:
176+ $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
177+ @echo
178+ @echo "Build finished. The XML files are in $(BUILDDIR)/xml."
179+
180+pseudoxml:
181+ $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
182+ @echo
183+ @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
docs/README.mdnew file+45
@@ -0,0 +1,45 @@
1+# Documentation for the Idris Language.
2+
3+
4+This manual has been prepared using ReStructured Text and the [Sphinx Documentation Generator](http://sphinx-doc.org) for future inclusion on [Read The Docs](http://www.readthedocs.org).
5+
6+## Dependencies
7+
8+To build the manual the following dependencies must be met. We assume that you have standard build automation tools already install i.e. `make`.
9+
10+### Sphinx-Doc
11+
12+Python should be installed by default on most systems.
13+Sphinx can be installed either through your hosts package manager or using pip/easy_install.
14+
15+*Note* [ReadTheDocs](http://www.readthedocs.org) works with Sphinx
16+ `v1.2.2`. If you install a more recent version of sphinx then
17+ 'incorrectly' marked up documentation may get passed the build system
18+ of readthedocs and be ignored. In the past we had several code-blocks
19+ disappear because of that.
20+
21+### LaTeX
22+
23+LaTeX can be install either using your systems package manager or direct from TeXLive.
24+
25+
26+## Build Instructions
27+
28+```sh
29+make html
30+make latexpdf
31+```
32+
33+## Contributing
34+
35+The documentation for Idris has been published under the Creative
36+Commons CC0 License. As such to the extent possible under law, /The
37+Idris Community/ has waived all copyright and related or neighboring
38+rights to Documentation for Idris.
39+
40+More information concerning the CC0 can be found online at:
41+
42+ http://creativecommons.org/publicdomain/zero/1.0/
43+
44+
45+When contributing material to the manual please bear in mind that the work will be licensed as above.
docs/conf.pynew file+357
@@ -0,0 +1,357 @@
1+# -*- coding: utf-8 -*-
2+#
3+# Idris Manual documentation build configuration file, created by
4+# sphinx-quickstart on Sat Feb 28 20:41:47 2015.
5+#
6+# This file is execfile()d with the current directory set to its
7+# containing dir.
8+#
9+# Note that not all possible configuration values are present in this
10+# autogenerated file.
11+#
12+# All configuration values have a default; values that are commented out
13+# serve to show the default.
14+
15+import sys
16+import os
17+
18+# If extensions (or modules to document with autodoc) are in another directory,
19+# add these directories to sys.path here. If the directory is relative to the
20+# documentation root, use os.path.abspath to make it absolute, like shown here.
21+#sys.path.insert(0, os.path.abspath('.'))
22+
23+# -- General configuration ------------------------------------------------
24+
25+# If your documentation needs a minimal Sphinx version, state it here.
26+#needs_sphinx = '1.0'
27+
28+# Add any Sphinx extension module names here, as strings. They can be
29+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
30+# ones.
31+extensions = [
32+ 'sphinx.ext.todo',
33+ 'sphinx.ext.pngmath',
34+ 'sphinx.ext.ifconfig',
35+]
36+
37+# Add any paths that contain templates here, relative to this directory.
38+templates_path = ['_templates']
39+
40+# The suffix of source filenames.
41+source_suffix = '.rst'
42+
43+# The encoding of source files.
44+#source_encoding = 'utf-8-sig'
45+
46+# The master toctree document.
47+master_doc = 'index'
48+
49+# General information about the project.
50+project = u'Idris'
51+copyright = u'2015, The Idris Community'
52+author = u'The Idris Community'
53+
54+# The version info for the project you're documenting, acts as replacement for
55+# |version| and |release|, also used in various other places throughout the
56+# built documents.
57+#
58+# The short X.Y version.
59+version = '0.9.17'
60+# The full version, including alpha/beta/rc tags.
61+release = '0.9.17'
62+
63+# The language for content autogenerated by Sphinx. Refer to documentation
64+# for a list of supported languages.
65+#
66+# This is also used if you do content translation via gettext catalogs.
67+# Usually you set "language" from the command line for these cases.
68+language = None
69+
70+# There are two options for replacing |today|: either, you set today to some
71+# non-false value, then it is used:
72+#today = ''
73+# Else, today_fmt is used as the format for a strftime call.
74+#today_fmt = '%B %d, %Y'
75+
76+# List of patterns, relative to source directory, that match files and
77+# directories to ignore when looking for source files.
78+exclude_patterns = ['_build']
79+
80+# The reST default role (used for this markup: `text`) to use for all
81+# documents.
82+#default_role = None
83+
84+# If true, '()' will be appended to :func: etc. cross-reference text.
85+#add_function_parentheses = True
86+
87+# If true, the current module name will be prepended to all description
88+# unit titles (such as .. function::).
89+#add_module_names = True
90+
91+# If true, sectionauthor and moduleauthor directives will be shown in the
92+# output. They are ignored by default.
93+#show_authors = False
94+
95+# The name of the Pygments (syntax highlighting) style to use.
96+pygments_style = 'sphinx'
97+
98+# A list of ignored prefixes for module index sorting.
99+#modindex_common_prefix = []
100+
101+# If true, keep warnings as "system message" paragraphs in the built documents.
102+#keep_warnings = False
103+
104+# If true, `todo` and `todoList` produce output, else they produce nothing.
105+todo_include_todos = True
106+
107+
108+# -- Options for HTML output ----------------------------------------------
109+
110+# The theme to use for HTML and HTML Help pages. See the documentation for
111+# a list of builtin themes.
112+html_theme = "default"
113+
114+# Theme options are theme-specific and customize the look and feel of a theme
115+# further. For a list of options available for each theme, see the
116+# documentation.
117+#html_theme_options = {}
118+
119+# Add any paths that contain custom themes here, relative to this directory.
120+#html_theme_path = []
121+
122+# The name for this set of Sphinx documents. If None, it defaults to
123+# "<project> v<release> documentation".
124+#html_title = None
125+
126+# A shorter title for the navigation bar. Default is the same as html_title.
127+#html_short_title = None
128+
129+# The name of an image file (relative to this directory) to place at the top
130+# of the sidebar.
131+#html_logo = None
132+
133+# The name of an image file (within the static path) to use as favicon of the
134+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
135+# pixels large.
136+#html_favicon = None
137+
138+# Add any paths that contain custom static files (such as style sheets) here,
139+# relative to this directory. They are copied after the builtin static files,
140+# so a file named "default.css" will overwrite the builtin "default.css".
141+html_static_path = ['_static']
142+
143+# Add any extra paths that contain custom files (such as robots.txt or
144+# .htaccess) here, relative to this directory. These files are copied
145+# directly to the root of the documentation.
146+#html_extra_path = []
147+
148+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
149+# using the given strftime format.
150+#html_last_updated_fmt = '%b %d, %Y'
151+
152+# If true, SmartyPants will be used to convert quotes and dashes to
153+# typographically correct entities.
154+#html_use_smartypants = True
155+
156+# Custom sidebar templates, maps document names to template names.
157+#html_sidebars = {}
158+
159+# Additional templates that should be rendered to pages, maps page names to
160+# template names.
161+#html_additional_pages = {}
162+
163+# If false, no module index is generated.
164+#html_domain_indices = True
165+
166+# If false, no index is generated.
167+#html_use_index = True
168+
169+# If true, the index is split into individual pages for each letter.
170+#html_split_index = False
171+
172+# If true, links to the reST sources are added to the pages.
173+#html_show_sourcelink = True
174+
175+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
176+#html_show_sphinx = True
177+
178+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
179+#html_show_copyright = True
180+
181+# If true, an OpenSearch description file will be output, and all pages will
182+# contain a <link> tag referring to it. The value of this option must be the
183+# base URL from which the finished HTML is served.
184+#html_use_opensearch = ''
185+
186+# This is the file name suffix for HTML files (e.g. ".xhtml").
187+#html_file_suffix = None
188+
189+# Language to be used for generating the HTML full-text search index.
190+# Sphinx supports the following languages:
191+# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
192+# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'
193+#html_search_language = 'en'
194+
195+# A dictionary with options for the search language support, empty by default.
196+# Now only 'ja' uses this config value
197+#html_search_options = {'type': 'default'}
198+
199+# The name of a javascript file (relative to the configuration directory) that
200+# implements a search results scorer. If empty, the default will be used.
201+#html_search_scorer = 'scorer.js'
202+
203+# Output file base name for HTML help builder.
204+htmlhelp_basename = 'IdrisManualdoc'
205+
206+# -- Options for LaTeX output ---------------------------------------------
207+
208+latex_elements = {
209+# The paper size ('letterpaper' or 'a4paper').
210+'papersize': 'a4paper',
211+
212+# The font size ('10pt', '11pt' or '12pt').
213+'pointsize': '10pt',
214+
215+# Additional stuff for the LaTeX preamble.
216+#'preamble': '',
217+
218+# Latex figure (float) alignment
219+#'figure_align': 'htbp',
220+}
221+
222+# Grouping the document tree into LaTeX files. List of tuples
223+# (source start file, target name, title,
224+# author, documentclass [howto, manual, or own class]).
225+latex_documents = [
226+ ('guides/index', 'idris-guides.tex', u'Idris Tutorial Series', u'The Idris Community', 'manual'),
227+ ('reference/index', 'idris-reference.tex', u'The Idris Reference', u'The Idris Community', 'manual'),
228+ ('tutorial/index', 'idris-tutorial.tex', u'The Idris Tutorial', u'The Idris Community', 'manual'),
229+ ('effects/index', 'eff-tutorial.tex', u'The Effects Tutorial', u'The Idris Community', 'manual')
230+ ]
231+
232+# The name of an image file (relative to this directory) to place at the top of
233+# the title page.
234+#latex_logo = None
235+
236+# For "manual" documents, if this is true, then toplevel headings are parts,
237+# not chapters.
238+#latex_use_parts = True
239+
240+# If true, show page references after internal links.
241+#latex_show_pagerefs = False
242+
243+# If true, show URL addresses after external links.
244+#latex_show_urls = False
245+
246+# Documents to append as an appendix to all manuals.
247+#latex_appendices = []
248+
249+# If false, no module index is generated.
250+#latex_domain_indices = True
251+
252+
253+# -- Options for manual page output ---------------------------------------
254+
255+# One entry per manual page. List of tuples
256+# (source start file, name, description, authors, manual section).
257+man_pages = [
258+ (master_doc, 'idrismanual', u'Idris Manual Documentation',
259+ [author], 1)
260+]
261+
262+# If true, show URL addresses after external links.
263+#man_show_urls = False
264+
265+
266+# -- Options for Texinfo output -------------------------------------------
267+
268+# Grouping the document tree into Texinfo files. List of tuples
269+# (source start file, target name, title, author,
270+# dir menu entry, description, category)
271+texinfo_documents = [
272+ (master_doc, 'IdrisManual', u'Idris Manual Documentation',
273+ author, 'IdrisManual', 'One line description of project.',
274+ 'Miscellaneous'),
275+]
276+
277+# Documents to append as an appendix to all manuals.
278+#texinfo_appendices = []
279+
280+# If false, no module index is generated.
281+#texinfo_domain_indices = True
282+
283+# How to display URL addresses: 'footnote', 'no', or 'inline'.
284+#texinfo_show_urls = 'footnote'
285+
286+# If true, do not generate a @detailmenu in the "Top" node's menu.
287+#texinfo_no_detailmenu = False
288+
289+
290+# -- Options for Epub output ----------------------------------------------
291+
292+# Bibliographic Dublin Core info.
293+epub_title = project
294+epub_author = author
295+epub_publisher = author
296+epub_copyright = copyright
297+
298+# The basename for the epub file. It defaults to the project name.
299+#epub_basename = project
300+
301+# The HTML theme for the epub output. Since the default themes are not optimized
302+# for small screen space, using the same theme for HTML and epub output is
303+# usually not wise. This defaults to 'epub', a theme designed to save visual
304+# space.
305+#epub_theme = 'epub'
306+
307+# The language of the text. It defaults to the language option
308+# or 'en' if the language is not set.
309+#epub_language = ''
310+
311+# The scheme of the identifier. Typical schemes are ISBN or URL.
312+#epub_scheme = ''
313+
314+# The unique identifier of the text. This can be a ISBN number
315+# or the project homepage.
316+#epub_identifier = ''
317+
318+# A unique identification for the text.
319+#epub_uid = ''
320+
321+# A tuple containing the cover image and cover page html template filenames.
322+#epub_cover = ()
323+
324+# A sequence of (type, uri, title) tuples for the guide element of content.opf.
325+#epub_guide = ()
326+
327+# HTML files that should be inserted before the pages created by sphinx.
328+# The format is a list of tuples containing the path and title.
329+#epub_pre_files = []
330+
331+# HTML files shat should be inserted after the pages created by sphinx.
332+# The format is a list of tuples containing the path and title.
333+#epub_post_files = []
334+
335+# A list of files that should not be packed into the epub file.
336+epub_exclude_files = ['search.html']
337+
338+# The depth of the table of contents in toc.ncx.
339+#epub_tocdepth = 3
340+
341+# Allow duplicate toc entries.
342+#epub_tocdup = True
343+
344+# Choose between 'default' and 'includehidden'.
345+#epub_tocscope = 'default'
346+
347+# Fix unsupported image types using the Pillow.
348+#epub_fix_images = False
349+
350+# Scale large images.
351+#epub_max_image_width = 0
352+
353+# How to display URL addresses: 'footnote', 'no', or 'inline'.
354+#epub_show_urls = 'inline'
355+
356+# If false, no index is generated.
357+#epub_use_index = True
docs/effects/conclusions.rstnew file+76
@@ -0,0 +1,76 @@
1+.. _sect-further:
2+
3+===============
4+Further Reading
5+===============
6+
7+This tutorial has given an introduction to writing and reasoning about
8+side-effecting programs in Idris, using the ``Effects`` library.
9+More details about the *implementation* of the library, such as how
10+``run`` works, how handlers are invoked, etc, are given in a separate
11+paper [1]_.
12+
13+Some libraries and programs which use ``Effects`` can be found in the
14+following places:
15+
16+- http://github.com/edwinb/SDL-idris — some bindings for the SDL media
17+ library, supporting graphics in particular.
18+
19+- http://github.com/edwinb/idris-demos — various demonstration
20+ programs, including several examples from this tutorial, and a “Space
21+ Invaders” game.
22+
23+- https://github.com/SimonJF/IdrisNet2 — networking and socket
24+ libraries.
25+
26+- http://github.com/edwinb/Protocols — a high level communication
27+ protocol description language.
28+
29+The inspiration for the ``Effects`` library was Bauer and Pretnar’s
30+Eff language [2]_, which describes a langauge based on algebraic
31+effects and handlers. Other recent languages and libraries have also
32+been built on this ideas, for example [3]_ and [4]_. The theoretical
33+foundations are also well-studied see [5]_, [6]_, [7]_, [8]_.
34+
35+
36+
37+.. [1] Edwin Brady. 2013. Programming and reasoning with algebraic
38+ effects and dependent types. SIGPLAN Not. 48, 9 (September
39+ 2013), 133-144. DOI=10.1145/2544174.2500581
40+ http://doi.acm.org/10.1145/2544174.2500581
41+
42+.. [2] Andrej Bauer, Matija Pretnar, Programming with algebraic
43+ effects and handlers, Journal of Logical and Algebraic Methods
44+ in Programming, Volume 84, Issue 1, January 2015, Pages
45+ 108-123, ISSN 2352-2208,
46+ http://dx.doi.org/10.1016/j.jlamp.2014.02.001.
47+ (http://www.sciencedirect.com/science/article/pii/S2352220814000194)
48+
49+.. [3] Ben Lippmeier. 2009. Witnessing Purity, Constancy and
50+ Mutability. In Proceedings of the 7th Asian Symposium on
51+ Programming Languages and Systems (APLAS '09), Zhenjiang Hu
52+ (Ed.). Springer-Verlag, Berlin, Heidelberg,
53+ 95-110. DOI=10.1007/978-3-642-10672-9_9
54+ http://dx.doi.org/10.1007/978-3-642-10672-9_9
55+
56+.. [4] Ohad Kammar, Sam Lindley, and Nicolas Oury. 2013. Handlers in
57+ action. SIGPLAN Not. 48, 9 (September 2013),
58+ 145-158. DOI=10.1145/2544174.2500590
59+ http://doi.acm.org/10.1145/2544174.2500590
60+
61+.. [5] Martin Hyland, Gordon Plotkin, John Power, Combining effects:
62+ Sum and tensor, Theoretical Computer Science, Volume 357,
63+ Issues 1–3, 25 July 2006, Pages 70-99, ISSN 0304-3975,
64+ http://dx.doi.org/10.1016/j.tcs.2006.03.013.
65+ (http://www.sciencedirect.com/science/article/pii/S0304397506002659)
66+
67+.. [6] Paul Blain Levy. 2004. Call-By-Push-Value: A
68+ Functional/Imperative Synthesis (Semantics Structures in
69+ Computation, V. 2). Kluwer Academic Publishers, Norwell, MA,
70+ USA.
71+
72+.. [7] Plotkin, Gordon, and Matija Pretnar. "Handlers of algebraic
73+ effects." Programming Languages and Systems. Springer Berlin
74+ Heidelberg, 2009. 80-94.
75+
76+.. [8] Pretnar, Matija. "Logic and handling of algebraic effects." (2010).
docs/effects/depeff.rstnew file+328
@@ -0,0 +1,328 @@
1+.. _sect-depeff:
2+
3+=================
4+Dependent Effects
5+=================
6+
7+In the programs we have seen so far, the available effects have remained
8+constant. Sometimes, however, an operation can *change* the available
9+effects. The simplest example occurs when we have a state with a
10+dependent type—adding an element to a vector also changes its type, for
11+example, since its length is explicit in the type. In this section, we
12+will see how the library supports this. Firstly, we will see how states
13+with dependent types can be implemented. Secondly, we will see how the
14+effects can depend on the *result* of an effectful operation. Finally,
15+we will see how this can be used to implement a type-safe and
16+resource-safe protocol for file management.
17+
18+Dependent States
19+----------------
20+
21+Suppose we have a function which reads input from the console, converts
22+it to an integer, and adds it to a list which is stored in a ``STATE``.
23+It might look something like the following:
24+
25+.. code-block:: idris
26+
27+ readInt : { [STATE (List Int), STDIO] } Eff ()
28+ readInt = do let x = trim !getStr
29+ put (cast x :: !get)
30+
31+But what if, instead of a list of integers, we would like to store a
32+``Vect``, maintaining the length in the type?
33+
34+.. code-block:: idris
35+
36+ readInt : { [STATE (Vect n Int), STDIO] } Eff ()
37+ readInt = do let x = trim !getStr
38+ put (cast x :: !get)
39+
40+This will not type check! Although the vector has length ``n`` on entry
41+to ``readInt``, it has length ``S n`` on exit. The library allows us to
42+express this as follows:
43+
44+.. code-block:: idris
45+
46+ readInt : { [STATE (Vect n Int), STDIO] ==>
47+ [STATE (Vect (S n) Int), STDIO] } Eff ()
48+ readInt = do let x = trim !getStr
49+ putM (cast x :: !get)
50+
51+The notation ``{ xs ==> xs’ } Eff a`` in a type means that the operation
52+begins with effects ``xs`` available, and ends with effects ``xs’``
53+available. We have used ``putM`` to update the state, where the ``M``
54+suffix indicates that the *type* is being updated as well as the value.
55+It has the following type:
56+
57+.. code-block:: idris
58+
59+ putM : y -> { [STATE x] ==> [STATE y] } Eff ()
60+
61+Result-dependent Effects
62+------------------------
63+
64+Often, whether a state is updated could depend on the success or
65+otherwise of an operation. In our ``readInt`` example, we might wish to
66+update the vector only if the input is a valid integer (i.e. all
67+digits). As a first attempt, we could try the following, returning a
68+``Bool`` which indicates success:
69+
70+.. code-block:: idris
71+
72+ readInt : { [STATE (Vect n Int), STDIO] ==>
73+ [STATE (Vect (S n) Int), STDIO] } Eff Bool
74+ readInt = do let x = trim !getStr
75+ case all isDigit (unpack x) of
76+ False => pure False
77+ True => do putM (cast x :: !get)
78+ pure True
79+
80+Unfortunately, this will not type check because the vector does not get
81+extended in both branches of the ``case``!
82+
83+::
84+
85+ MutState.idr:18:19:When elaborating right hand side of Main.case
86+ block in readInt:
87+ Unifying n and S n would lead to infinite value
88+
89+Clearly, the size of the resulting vector depends on whether or not the
90+value read from the user was valid. We can express this in the type:
91+
92+.. code-block:: idris
93+
94+ readInt : { [STATE (Vect n Int), STDIO] ==>
95+ {ok} if ok then [STATE (Vect (S n) Int), STDIO]
96+ else [STATE (Vect n Int), STDIO] } Eff Bool
97+ readInt = do let x = trim !getStr
98+ case all isDigit (unpack x) of
99+ False => pure False
100+ True => do putM (cast x :: !get)
101+ pure True
102+
103+The notation ``{ xs ==> res xs’ } Eff a`` in a type means that the
104+effects available are updated from ``xs`` to ``xs’``, *and* the
105+resulting effects ``xs’`` may depend on the result of the operation
106+``res``, of type ``a``. Here, the resulting effects are computed from
107+the result ``ok``—if ``True``, the vector is extended, otherwise it
108+remains the same.
109+
110+When using the function, we will naturally have to check its return
111+value in order to know what the new set of effects is. For example, to
112+read a set number of values into a vector, we could write the following:
113+
114+.. code-block:: idris
115+
116+ readN : (n : Nat) ->
117+ { [STATE (Vect m Int), STDIO] ==>
118+ [STATE (Vect (n + m) Int), STDIO] } Eff ()
119+ readN Z = pure ()
120+ readN {m} (S k) = case !readInt of
121+ True => rewrite plusSuccRightSucc k m in readN k
122+ False => readN (S k)
123+
124+The ``case`` analysis on the result of ``readInt`` means that we know in
125+each branch whether reading the integer succeeded, and therefore how
126+many values still need to be read into the vector. What this means in
127+practice is that the type system has verified that a necessary dynamic
128+check (i.e. whether reading a value succeeded) has indeed been done.
129+
130+.. note::
131+ Only ``case`` will work here. We cannot use ``if/then/else``
132+ because the ``then`` and ``else`` branches must have the same
133+ type. The ``case`` construct, however, abstracts over the value
134+ being inspected in the type of each branch.
135+
136+File Management
137+---------------
138+
139+A practical use for dependent effects is in specifying resource usage
140+protocols and verifying that they are executed correctly. For example,
141+file management follows a resource usage protocol with the following
142+(informally specified) requirements:
143+
144+- It is necessary to open a file for reading before reading it
145+
146+- Opening may fail, so the programmer should check whether opening was
147+ successful
148+
149+- A file which is open for reading must not be written to, and vice
150+ versa
151+
152+- When finished, an open file handle should be closed
153+
154+- When a file is closed, its handle should no longer be used
155+
156+These requirements can be expressed formally in , by creating a
157+``FILE_IO`` effect parameterised over a file handle state, which is
158+either empty, open for reading, or open for writing. The ``FILE_IO``
159+effect’s definition is given below. Note that this
160+effect is mainly for illustrative purposes—typically we would also like
161+to support random access files and better reporting of error conditions.
162+
163+.. code-block:: idris
164+
165+ module Effect.File
166+
167+ import Effects
168+ import Control.IOExcept
169+
170+ FILE_IO : Type -> EFFECT
171+
172+ data OpenFile : Mode -> Type
173+
174+ open : String -> (m : Mode) ->
175+ { [FILE_IO ()] ==>
176+ {ok} [FILE_IO (if ok then OpenFile m else ())] } Eff Bool
177+ close : { [FILE_IO (OpenFile m)] ==> [FILE_IO ()] } Eff ()
178+
179+ readLine : { [FILE_IO (OpenFile Read)] } Eff String
180+ writeLine : { [FILE_IO (OpenFile Write)] } Eff ()
181+ eof : { [FILE_IO (OpenFile Read)] } Eff Bool
182+
183+ instance Handler FileIO IO
184+
185+In particular, consider the type of ``open``:
186+
187+.. code-block:: idris
188+
189+ open : String -> (m : Mode) ->
190+ { [FILE_IO ()] ==>
191+ {ok} [FILE_IO (if ok then OpenFile m else ())] } Eff Bool
192+
193+This returns a ``Bool`` which indicates whether opening the file was
194+successful. The resulting state depends on whether the operation was
195+successful; if so, we have a file handle open for the stated purpose,
196+and if not, we have no file handle. By ``case`` analysis on the result,
197+we continue the protocol accordingly.
198+
199+.. _eff-readfile:
200+.. code-block:: idris
201+
202+ readFile : { [FILE_IO (OpenFile Read)] } Eff (List String)
203+ readFile = readAcc [] where
204+ readAcc : List String -> { [FILE_IO (OpenFile Read)] }
205+ Eff (List String)
206+ readAcc acc = if (not !eof)
207+ then readAcc (!readLine :: acc)
208+ else pure (reverse acc)
209+
210+Given a function ``readFile``, above, which reads from
211+an open file until reaching the end, we can write a program which opens
212+a file, reads it, then displays the contents and closes it, as follows,
213+correctly following the protocol:
214+
215+.. code-block:: idris
216+
217+ dumpFile : String -> { [FILE_IO (), STDIO] } Eff ()
218+ dumpFile name = case !(open name Read) of
219+ True => do putStrLn (show !readFile)
220+ close
221+ False => putStrLn ("Error!")
222+
223+The type of ``dumpFile``, with ``FILE_IO ()`` in its effect list,
224+indicates that any use of the file resource will follow the protocol
225+correctly (i.e. it both begins and ends with an empty resource). If we
226+fail to follow the protocol correctly (perhaps by forgetting to close
227+the file, failing to check that ``open`` succeeded, or opening the file
228+for writing) then we will get a compile-time error. For example,
229+changing ``open name Read`` to ``open name Write`` yields a compile-time
230+error of the following form:
231+
232+::
233+
234+ FileTest.idr:16:18:When elaborating right hand side of Main.case
235+ block in testFile:
236+ Can't solve goal
237+ SubList [(FILE_IO (OpenFile Read))]
238+ [(FILE_IO (OpenFile Write)), STDIO]
239+
240+In other words: when reading a file, we need a file which is open for
241+reading, but the effect list contains a ``FILE_IO`` effect carrying a
242+file open for writing.
243+
244+Pattern-matching bind
245+---------------------
246+
247+It might seem that having to test each potentially failing operation
248+with a ``case`` clause could lead to ugly code, with lots of
249+nested case blocks. Many languages support exceptions to improve this,
250+but unfortunately exceptions may not allow completely clean resource
251+management—for example, guaranteeing that any ``open`` which did succeed
252+has a corresponding close.
253+
254+Idris supports *pattern-matching* bindings, such as the following:
255+
256+.. code-block:: idris
257+
258+ dumpFile : String -> { [FILE_IO (), STDIO] } Eff ()
259+ dumpFile name = do True <- open name Read
260+ putStrLn (show !readFile)
261+ close
262+
263+This also has a problem: we are no longer dealing with the case where
264+opening a file failed! The solution is to extend the pattern-matching
265+binding syntax to give brief clauses for failing matches. Here, for
266+example, we could write:
267+
268+.. code-block:: idris
269+
270+ dumpFile : String -> { [FILE_IO (), STDIO] } Eff ()
271+ dumpFile name = do True <- open name Read | False => putStrLn "Error"
272+ putStrLn (show !readFile)
273+ close
274+
275+This is exactly equivalent to the definition with the explicit ``case``.
276+In general, in a ``do``-block, the syntax:
277+
278+.. code-block:: idris
279+
280+ do pat <- val | <alternatives>
281+ p
282+
283+is desugared to
284+
285+.. code-block:: idris
286+
287+ do x <- val
288+ case x of
289+ pat => p
290+ <alternatives>
291+
292+There can be several ``alternatives``, separated by a vertical bar
293+``|``. For example, there is a ``SYSTEM`` effect which supports
294+reading command line arguments, among other things (see Appendix
295+:ref:`sect-appendix`). To read command line arguments, we can use
296+``getArgs``:
297+
298+.. code-block:: idris
299+
300+ getArgs : { [SYSTEM] } Eff (List String)
301+
302+A main program can read command line arguments as follows, where in the
303+list which is returned, the first element ``prog`` is the executable
304+name and the second is an expected argument:
305+
306+.. code-block:: idris
307+
308+ emain : { [SYSTEM, STDIO] } Eff ()
309+ emain = do [prog, arg] <- getArgs
310+ putStrLn $ "Argument is " ++ arg
311+ {- ... rest of function ... -}
312+
313+Unfortunately, this will not fail gracefully if no argument is given, or
314+if too many arguments are given. We can use pattern matching bind
315+alternatives to give a better (more informative) error:
316+
317+.. code-block:: idris
318+
319+ emain : { [SYSTEM, STDIO] } Eff ()
320+ emain = do [prog, arg] <- getArgs | [] => putStrLn "Can't happen!"
321+ | [prog] => putStrLn "No arguments!"
322+ | _ => putStrLn "Too many arguments!"
323+ putStrLn $ "Argument is " ++ arg
324+ {- ... rest of function ... -}
325+
326+If ``getArgs`` does not return something of the form ``[prog, arg]`` the
327+alternative which does match is executed instead, and that value
328+returned.
docs/effects/hangman.rstnew file+333
@@ -0,0 +1,333 @@
1+.. _sect-hangman:
2+
3+=======================================
4+Example: A “Mystery Word” Guessing Game
5+=======================================
6+
7+In this section, we will use the techniques and specific effects
8+discussed in the tutorial so far to implement a larger example, a simple
9+text-based word-guessing game. In the game, the computer chooses a word,
10+which the player must guess letter by letter. After a limited number of
11+wrong guesses, the player loses [1]_.
12+
13+We will implement the game by following these steps:
14+
15+#. Define the game state, in enough detail to express the rules
16+
17+#. Define the rules of the game (i.e. what actions the player may take,
18+ and how these actions affect the game state)
19+
20+#. Implement the rules of the game (i.e. implement state updates for
21+ each action)
22+
23+#. Implement a user interface which allows a player to direct actions
24+
25+Step 2 may be achieved by defining an effect which depends on the state
26+defined in step 1. Then step 3 involves implementing a ``Handler`` for
27+this effect. Finally, step 4 involves implementing a program in ``Eff``
28+using the newly defined effect (and any others required to implement the
29+interface).
30+
31+Step 1: Game State
32+------------------
33+
34+First, we categorise the game states as running games (where there are a
35+number of guesses available, and a number of letters still to guess), or
36+non-running games (i.e. games which have not been started, or games
37+which have been won or lost).
38+
39+.. code-block:: idris
40+
41+ data GState = Running Nat Nat | NotRunning
42+
43+Notice that at this stage, we say nothing about what it means to make a
44+guess, what the word to be guessed is, how to guess letters, or any
45+other implementation detail. We are only interested in what is necessary
46+to describe the game rules.
47+
48+We will, however, parameterise a concrete game state ``Mystery`` over
49+this data:
50+
51+.. code-block:: idris
52+
53+ data Mystery : GState -> Type
54+
55+Step 2: Game Rules
56+------------------
57+
58+We describe the game rules as a dependent effect, where each action has
59+a *precondition* (i.e. what the game state must be before carrying out
60+the action) and a *postcondition* (i.e. how the action affects the game
61+state). Informally, these actions with the pre- and postconditions are:
62+
63+Guess
64+ Guess a letter in the word.
65+
66+ - Precondition: The game must be running, and there must be both
67+ guesses still available, and letters still to be guessed.
68+
69+ - Postcondition: If the guessed letter is in the word and not yet
70+ guessed, reduce the number of letters, otherwise reduce the
71+ number of guesses.
72+
73+Won
74+ Declare victory
75+
76+ - Precondition: The game must be running, and there must be no
77+ letters still to be guessed.
78+
79+ - Postcondition: The game is no longer running.
80+
81+Lost
82+ Accept defeat
83+
84+ - Precondition: The game must be running, and there must be no
85+ guesses left.
86+
87+ - Postcondition: The game is no longer running.
88+
89+NewWord
90+ Set a new word to be guessed
91+
92+ - Precondition: The game must not be running.
93+
94+ - Postcondition: The game is running, with 6 guesses available (the
95+ choice of 6 is somewhat arbitrary here) and the number of unique
96+ letters in the word still to be guessed.
97+
98+StrState
99+ Get a string representation of the game state. This is for display
100+ purposes; there are no pre- or postconditions.
101+
102+We can make these rules precise by declaring them more formally in an
103+effect signature:
104+
105+.. code-block:: idris
106+
107+ data MysteryRules : Effect where
108+ Guess : (x : Char) ->
109+ { Mystery (Running (S g) (S w)) ==>
110+ {inword} if inword then Mystery (Running (S g) w)
111+ else Mystery (Running g (S w)) }
112+ MysteryRules Bool
113+ Won : { Mystery (Running g 0) ==> Mystery NotRunning } MysteryRules ()
114+ Lost : { Mystery (Running 0 g) ==> Mystery NotRunning } MysteryRules ()
115+ NewWord : (w : String) ->
116+ { Mystery NotRunning ==>
117+ Mystery (Running 6 (length (letters w))) } MysteryRules ()
118+ StrState : { Mystery h } MysteryRules String
119+
120+This description says nothing about how the rules are implemented. In
121+particular, it does not specify *how* to tell whether a guessed letter
122+was in a word, just that the result of ``Guess`` depends on it.
123+
124+Nevertheless, we can still create an ``EFFECT`` from this, and use it in
125+an ``Eff`` program. Implementing a ``Handler`` for ``MysteryRules`` will
126+then allow us to play the game.
127+
128+.. code-block:: idris
129+
130+ MYSTERY : GState -> EFFECT
131+ MYSTERY h = MkEff (Mystery h) MysteryRules
132+
133+Step 3: Implement Rules
134+-----------------------
135+
136+To *implement* the rules, we begin by giving a concrete definition of
137+game state:
138+
139+.. code-block:: idris
140+
141+ data Mystery : GState -> Type where
142+ Init : Mystery NotRunning
143+ GameWon : (word : String) -> Mystery NotRunning
144+ GameLost : (word : String) -> Mystery NotRunning
145+ MkG : (word : String) ->
146+ (guesses : Nat) ->
147+ (got : List Char) ->
148+ (missing : Vect m Char) ->
149+ Mystery (Running guesses m)
150+
151+If a game is ``NotRunning``, that is either because it has not yet
152+started (``Init``) or because it is won or lost (``GameWon`` and
153+``GameLost``, each of which carry the word so that showing the game
154+state will reveal the word to the player). Finally, ``MkG`` captures a
155+running game’s state, including the target word, the letters
156+successfully guessed, and the missing letters. Using a ``Vect`` for the
157+missing letters is convenient since its length is used in the type.
158+
159+To initialise the state, we implement the following functions:
160+``letters``, which returns a list of unique letters in a ``String``
161+(ignoring spaces) and ``initState`` which sets up an initial state
162+considered valid as a postcondition for ``NewWord``.
163+
164+.. code-block:: idris
165+
166+ letters : String -> List Char
167+ initState : (x : String) -> Mystery (Running 6 (length (letters x)))
168+
169+When checking if a guess is in the vector of missing letters, it is
170+convenient to return a *proof* that the guess is in the vector, using
171+``isElem`` below, rather than merely a ``Bool``:
172+
173+.. code-block:: idris
174+
175+ data IsElem : a -> Vect n a -> Type where
176+ First : IsElem x (x :: xs)
177+ Later : IsElem x xs -> IsElem x (y :: xs)
178+
179+ isElem : DecEq a => (x : a) -> (xs : Vect n a) -> Maybe (IsElem x xs)
180+
181+The reason for returning a proof is that we can use it to remove an
182+element from the correct position in a vector:
183+
184+.. code-block:: idris
185+
186+ shrink : (xs : Vect (S n) a) -> IsElem x xs -> Vect n a
187+
188+We leave the definitions of ``letters``, ``init``, ``isElem`` and
189+``shrink`` as exercises. Having implemented these, the ``Handler``
190+implementation for ``MysteryRules`` is surprisingly straightforward:
191+
192+.. code-block:: idris
193+
194+ instance Handler MysteryRules m where
195+ handle (MkG w g got []) Won k = k () (GameWon w)
196+ handle (MkG w Z got m) Lost k = k () (GameLost w)
197+
198+ handle st StrState k = k (show st) st
199+ handle st (NewWord w) k = k () (initState w)
200+
201+ handle (MkG w (S g) got m) (Guess x) k =
202+ case isElem x m of
203+ Nothing => k False (MkG w _ got m)
204+ (Just p) => k True (MkG w _ (x :: got) (shrink m p))
205+
206+Each case simply involves directly updating the game state in a way
207+which is consistent with the declared rules. In particular, in
208+``Guess``, if the handler claims that the guessed letter is in the word
209+(by passing ``True`` to ``k``), there is no way to update the state in
210+such a way that the number of missing letters or number of guesses does
211+not follow the rules.
212+
213+Step 4: Implement Interface
214+---------------------------
215+
216+Having described the rules, and implemented state transitions which
217+follow those rules as an effect handler, we can now write an interface
218+for the game which uses the ``MYSTERY`` effect:
219+
220+.. code-block:: idris
221+
222+ game : { [MYSTERY (Running (S g) w), STDIO] ==>
223+ [MYSTERY NotRunning, STDIO] } Eff ()
224+
225+The type indicates that the game must start in a running state, with
226+some guesses available, and eventually reach a not-running state (i.e.
227+won or lost). The only way to achieve this is by correctly following the
228+stated rules.
229+
230+Note that the type of ``game`` makes no assumption that there are
231+letters to be guessed in the given word (i.e. it is ``w`` rather than
232+``S w``). This is because we will be choosing a word at random from a
233+vector of ``String``, and at no point have we made it explicit that
234+those ``String`` are non-empty.
235+
236+Finally, we need to initialise the game by picking a word at random from
237+a list of candidates, setting it as the target using ``NewWord``, then
238+running ``game``:
239+
240+.. code-block:: idris
241+
242+ runGame : { [MYSTERY NotRunning, RND, SYSTEM, STDIO] } Eff ()
243+ runGame = do srand (cast !time)
244+ let w = index !(rndFin WEWEWE) words
245+ NewWord w
246+ game
247+ putStrLn !StrState
248+
249+We use the system time (``time`` from the ``SYSTEM`` effect; see
250+Appendix :ref:`sect-appendix`) to initialise the random number
251+generator, then pick a random ``Fin`` to index into a list of
252+``words``. For example, we could initialise a word list as follows:
253+
254+.. code-block:: idris
255+
256+ words : ?wtype
257+ words = with Vect ["idris","agda","haskell","miranda",
258+ "java","javascript","fortran","basic",
259+ "coffeescript","rust"]
260+
261+ wtype = proof search
262+
263+.. note::
264+ Rather than have to explicitly declare a type with the vector’s
265+ length, it is convenient to give a metavariable ``?wtype`` and let
266+ Idris’s proof search mechanism find the type. This is a
267+ limited form of type inference, but very useful in practice.
268+
269+A possible complete implementation of ``game`` is
270+presented below:
271+
272+.. code-block:: idris
273+
274+ game : { [MYSTERY (Running (S g) w), STDIO] ==>
275+ [MYSTERY NotRunning, STDIO] } Eff ()
276+ game {w=Z} = Won
277+ game {w=S _}
278+ = do putStrLn !StrState
279+ putStr "Enter guess: "
280+ let guess = trim !getStr
281+ case choose (not (guess == "")) of
282+ (Left p) => processGuess (strHead' guess p)
283+ (Right p) => do putStrLn "Invalid input!"
284+ game
285+ where
286+ processGuess : Char -> { [MYSTERY (Running (S g) (S w)), STDIO] ==>
287+ [MYSTERY NotRunning, STDIO] }
288+ Eff ()
289+ processGuess {g} {w} c
290+ = case !(Main.Guess c) of
291+ True => do putStrLn "Good guess!"
292+ case w of
293+ Z => Won
294+ (S k) => game
295+ False => do putStrLn "No, sorry"
296+ case g of
297+ Z => Lost
298+ (S k) => game
299+
300+Discussion
301+----------
302+
303+Writing the rules separately as an effect, then an implementation
304+which uses that effect, ensures that the implementation must follow
305+the rules. This has practical applications in more serious contexts;
306+``MysteryRules`` for example can be though of as describing a
307+*protocol* that a game player most follow, or alternative a
308+*precisely-typed API*.
309+
310+In practice, we wouldn’t really expect to write rules first then
311+implement the game once the rules were complete. Indeed, I didn’t do
312+so when constructing this example! Rather, I wrote down a set of
313+likely rules making any assumptions *explicit* in the state
314+transitions for ``MysteryRules``. Then, when implementing ``game`` at
315+first, any incorrect assumption was caught as a type error. The
316+following errors were caught during development:
317+
318+- Not realising that allowing ``NewWord`` to be an arbitrary string
319+ would mean that ``game`` would have to deal with a zero-length word
320+ as a starting state.
321+
322+- Forgetting to check whether a game was won before recursively
323+ calling ``processGuess``, thus accidentally continuing a finished
324+ game.
325+
326+- Accidentally checking the number of missing letters, rather than the
327+ number of remaining guesses, when checking if a game was lost.
328+
329+These are, of course, simple errors, but were caught by the type
330+checker before any testing of the game.
331+
332+.. [1]
333+ Readers may recognise this game by the name “Hangman.”
docs/effects/impleff.rstnew file+323
@@ -0,0 +1,323 @@
1+.. _sect-impleff:
2+
3+====================
4+Creating New Effects
5+====================
6+
7+We have now seen several side-effecting operations provided by the
8+``Effects`` library, and examples of their use in Section
9+:ref:`sect-simpleff`. We have also seen how operations may *modify*
10+the available effects by changing state in Section
11+:ref:`sect-depeff`. We have not, however, yet seen how these
12+operations are implemented. In this section, we describe how a
13+selection of the available effects are implemented, and show how new
14+effectful operations may be provided.
15+
16+State
17+-----
18+
19+Effects are described by *algebraic data types*, where the
20+constructors describe the operations provided when the effect is
21+available. Stateful operations are described as follows:
22+
23+.. code-block:: idris
24+
25+ data State : Effect where
26+ Get : { a } State a
27+ Put : b -> { a ==> b } State ()
28+
29+Each effect is associated with a *resource*, the type of which is
30+given with the notation ``{ x ==> x’ }``. This notation gives the
31+resource type expected by each operation, and how it updates when the
32+operation is run. Here, it means:
33+
34+- ``Get`` takes no arguments. It has a resource of type ``a``, which
35+ is not updated, and running the ``Get`` operation returns something
36+ of type ``a``.
37+
38+- ``Put`` takes a ``b`` as an argument. It has a resource of type
39+ ``a`` on input, which is updated to a resource of type
40+ ``b``. Running the ``Put`` operation returns the element of the
41+ unit type.
42+
43+``Effect`` itself is a type synonym, declared as follows:
44+
45+.. code-block:: idris
46+
47+ Effect : Type
48+ Effect = (result : Type) ->
49+ (input_resource : Type) ->
50+ (output_resource : result -> Type) -> Type
51+
52+That is, an effectful operation returns something of type ``result``,
53+has an input resource of type ``input_resource``, and a function
54+``output_resource`` which computes the output resource type from the
55+result. We use the same syntactic sugar as with ``Eff`` to make effect
56+declarations more readable. It is defined as follows in the library:
57+
58+.. code-block:: idris
59+
60+ syntax "{" [inst] "}" [eff] = eff inst (\result => inst)
61+ syntax "{" [inst] "==>" "{" {b} "}" [outst] "}" [eff]
62+ = eff inst (\b => outst)
63+ syntax "{" [inst] "==>" [outst] "}" [eff] = eff inst (\result => outst)
64+
65+In order to convert ``State`` (of type ``Effect``) into something
66+usable in an effects list, of type ``EFFECT``, we write the following:
67+
68+.. code-block:: idris
69+
70+ STATE : Type -> EFFECT
71+ STATE t = MkEff t State
72+
73+``MkEff`` constructs an ``EFFECT`` by taking the resource type (here,
74+the ``t`` which parameterises ``STATE``) and the effect signature
75+(here, ``State``). For reference, ``EFFECT`` is declared as follows:
76+
77+.. code-block:: idris
78+
79+ data EFFECT : Type where
80+ MkEff : Type -> Effect -> EFFECT
81+
82+Recall that to run an effectful program in ``Eff``, we use one of the
83+``run`` family of functions to run the program in a particular
84+computation context ``m``. For each effect, therefore, we must explain
85+how it is executed in a particular computation context for ``run`` to
86+work in that context. This is achieved with the following type class:
87+
88+.. code-block:: idris
89+
90+ class Handler (e : Effect) (m : Type -> Type) where
91+ handle : resource -> (eff : e t resource resource') ->
92+ ((x : t) -> resource' x -> m a) -> m a
93+
94+We have already seen some instance declarations in the effect
95+summaries in Section :ref:`sect-simpleff`. An instance of ``Handler e
96+m`` means that the effect declared with signature ``e`` can be run in
97+computation context ``m``. The ``handle`` function takes:
98+
99+- The ``resource`` on input (so, the current value of the state for
100+ ``State``)
101+
102+- The effectful operation (either ``Get`` or ``Put x`` for ``State``)
103+
104+- A *continuation*, which we conventionally call ``k``, and should be
105+ passed the result value of the operation, and an updated resource.
106+
107+There are two reasons for taking a continuation here: firstly, this is
108+neater because there are multiple return values (a new resource and
109+the result of the operation); secondly, and more importantly, the
110+continuation can be called zero or more times.
111+
112+A ``Handler`` for ``State`` simply passes on the value of the state,
113+in the case of ``Get``, or passes on a new state, in the case of
114+``Put``. It is defined the same way for all computation contexts:
115+
116+.. code-block:: idris
117+
118+ instance Handler State m where
119+ handle st Get k = k st st
120+ handle st (Put n) k = k () n
121+
122+This gives enough information for ``Get`` and ``Put`` to be used
123+directly in ``Eff`` programs. It is tidy, however, to define top level
124+functions in ``Eff``, as follows:
125+
126+.. code-block:: idris
127+
128+ get : { [STATE x] } Eff x
129+ get = call Get
130+
131+ put : x -> { [STATE x] } Eff ()
132+ put val = call (Put val)
133+
134+ putM : y -> { [STATE x] ==> [STATE y] } Eff ()
135+ putM val = call (Put val)
136+
137+**An implementation detail (aside):** The ``call`` function converts
138+an ``Effect`` to a function in ``Eff``, given a proof that the effect
139+is available. This proof can be constructed automatically by , since
140+it is essentially an index into a statically known list of effects:
141+
142+.. code-block:: idris
143+
144+ call : {e : Effect} ->
145+ (eff : e t a b) -> {auto prf : EffElem e a xs} ->
146+ Eff t xs (\v => updateResTy v xs prf eff)
147+
148+This is the reason for the ``Can’t solve goal`` error when an effect
149+is not available: the implicit proof ``prf`` has not been solved
150+automatically because the required effect is not in the list of
151+effects ``xs``.
152+
153+Such details are not important for using the library, or even writing
154+new effects, however.
155+
156+Summary
157+~~~~~~~
158+
159+The following listing summarises what is required to define the
160+``STATE`` effect:
161+
162+.. code-block:: idris
163+
164+ data State : Effect where
165+ Get : { a } State a
166+ Put : b -> { a ==> b } State ()
167+
168+ STATE : Type -> EFFECT
169+ STATE t = MkEff t State
170+
171+ instance Handler State m where
172+ handle st Get k = k st st
173+ handle st (Put n) k = k () n
174+
175+ get : { [STATE x] } Eff x
176+ get = call Get
177+
178+ put : x -> { [STATE x] } Eff ()
179+ put val = call (Put val)
180+
181+ putM : y -> { [STATE x] ==> [STATE y] } Eff ()
182+ putM val = call (Put val)
183+
184+
185+Console I/O
186+-----------
187+
188+Then listing below gives the definition of the ``STDIO``
189+effect, including handlers for ``IO`` and ``IOExcept``. We omit the
190+definition of the top level ``Eff`` functions, as this merely invoke
191+the effects ``PutStr``, ``GetStr``, ``PutCh`` and ``GetCh`` directly.
192+
193+Note that in this case, the resource is the unit type in every case,
194+since the handlers merely apply the ``IO`` equivalents of the effects
195+directly.
196+
197+.. _eff-stdiodef:
198+.. code-block:: idris
199+
200+ data StdIO : Effect where
201+ PutStr : String -> { () } StdIO ()
202+ GetStr : { () } StdIO String
203+ PutCh : Char -> { () } StdIO ()
204+ GetCh : { () } StdIO Char
205+
206+ instance Handler StdIO IO where
207+ handle () (PutStr s) k = do putStr s; k () ()
208+ handle () GetStr k = do x <- getLine; k x ()
209+ handle () (PutCh c) k = do putChar c; k () ()
210+ handle () GetCh k = do x <- getChar; k x ()
211+
212+ instance Handler StdIO (IOExcept a) where
213+ handle () (PutStr s) k = do ioe_lift $ putStr s; k () ()
214+ handle () GetStr k = do x <- ioe_lift $ getLine; k x ()
215+ handle () (PutCh c) k = do ioe_lift $ putChar c; k () ()
216+ handle () GetCh k = do x <- ioe_lift $ getChar; k x ()
217+
218+ STDIO : EFFECT
219+ STDIO = MkEff () StdIO
220+
221+Exceptions
222+----------
223+
224+The listing below gives the definition of the ``Exception``
225+effect, including two of its handlers for ``Maybe`` and ``List``. The
226+only operation provided is ``Raise``. The key point to note in the
227+definitions of these handlers is that the continuation ``k`` is not
228+used. Running ``Raise`` therefore means that computation stops with an
229+error.
230+
231+.. code-block:: idris
232+
233+ data Exception : Type -> Effect where
234+ Raise : a -> { () } Exception a b
235+
236+ instance Handler (Exception a) Maybe where
237+ handle _ (Raise e) k = Nothing
238+
239+ instance Handler (Exception a) List where
240+ handle _ (Raise e) k = []
241+
242+ EXCEPTION : Type -> EFFECT
243+ EXCEPTION t = MkEff () (Exception t)
244+
245+
246+Non-determinism
247+---------------
248+
249+The following listing gives the definition of the ``Select``
250+effect for writing non-deterministic programs, including a handler for
251+``List`` context which returns all possible successful values, and a
252+handler for ``Maybe`` context which returns the first successful
253+value.
254+
255+.. code-block:: idris
256+
257+ data Selection : Effect where
258+ Select : List a -> { () } Selection a
259+
260+ instance Handler Selection Maybe where
261+ handle _ (Select xs) k = tryAll xs where
262+ tryAll [] = Nothing
263+ tryAll (x :: xs) = case k x () of
264+ Nothing => tryAll xs
265+ Just v => Just v
266+
267+ instance Handler Selection List where
268+ handle r (Select xs) k = concatMap (\x => k x r) xs
269+
270+ SELECT : EFFECT
271+ SELECT = MkEff () Selection
272+
273+
274+Here, the continuation is called multiple times in each handler, for
275+each value in the list of possible values. In the ``List`` handler, we
276+accumulate all successful results, and in the ``Maybe`` handler we try
277+the first value in the last, and try later values only if that fails.
278+
279+File Management
280+---------------
281+
282+Result-dependent effects are no different from non-dependent effects
283+in the way they are implemented. The listing below
284+illustrates this for the ``FILE_IO`` effect. The syntax for state
285+transitions ``{ x ==> {res} x’ }``, where the result state ``x’`` is
286+computed from the result of the operation ``res``, follows that for
287+the equivalent ``Eff`` programs.
288+
289+.. code-block:: idris
290+
291+ data FileIO : Effect where
292+ Open : String -> (m : Mode) ->
293+ {() ==> {res} if res then OpenFile m else ()} FileIO Bool
294+ Close : {OpenFile m ==> ()} FileIO ()
295+
296+ ReadLine : {OpenFile Read} FileIO String
297+ WriteLine : String -> {OpenFile Write} FileIO ()
298+ EOF : {OpenFile Read} FileIO Bool
299+
300+ instance Handler FileIO IO where
301+ handle () (Open fname m) k = do h <- openFile fname m
302+ if !(validFile h)
303+ then k True (FH h)
304+ else k False ()
305+ handle (FH h) Close k = do closeFile h
306+ k () ()
307+
308+ handle (FH h) ReadLine k = do str <- fread h
309+ k str (FH h)
310+ handle (FH h) (WriteLine str) k = do fwrite h str
311+ k () (FH h)
312+ handle (FH h) EOF k = do e <- feof h
313+ k e (FH h)
314+
315+ FILE_IO : Type -> EFFECT
316+ FILE_IO t = MkEff t FileIO
317+
318+Note that in the handler for ``Open``, the types passed to the
319+continuation ``k`` are different depending on whether the result is
320+``True`` (opening succeeded) or ``False`` (opening failed). This uses
321+``validFile``, defined in the ``Prelude``, to test whether a file
322+handler refers to an open file or not.
323+
docs/effects/index.rstnew file+28
@@ -0,0 +1,28 @@
1+.. _eff-tutorial-index:
2+
3+####################
4+The Effects Tutorial
5+####################
6+
7+A tutorial on the `Effects` package in `Idris`.
8+
9+.. note::
10+
11+ The documentation for Idris has been published under the Creative
12+ Commons CC0 License. As such to the extent possible under law, *The
13+ Idris Community* has waived all copyright and related or neighboring
14+ rights to Documentation for Idris.
15+
16+ More information concerning the CC0 can be found online at: http://creativecommons.org/publicdomain/zero/1.0/
17+
18+.. toctree::
19+ :maxdepth: 1
20+
21+ introduction
22+ state
23+ simpleeff
24+ depeff
25+ impleff
26+ hangman
27+ conclusions
28+ summary
docs/effects/introduction.rstnew file+113
@@ -0,0 +1,113 @@
1+============
2+Introduction
3+============
4+
5+Pure functional languages with dependent types such as `Idris
6+<http://idris-lang.org/>`_ support reasoning about programs directly
7+in the type system, promising that we can *know* a program will run
8+correctly (i.e. according to the specification in its type) simply
9+because it compiles. Realistically, though, things are not so simple:
10+programs have to interact with the outside world, with user input,
11+input from a network, mutable state, and so on. In this tutorial I
12+will introduce the library, which is included with the distribution
13+and supports programming and reasoning with side-effecting programs,
14+supporting mutable state, interaction with the outside world,
15+exceptions, and verified resource management.
16+
17+This tutorial assumes familiarity with pure programming in Idris,
18+as described in Sections 1–6 of the main tutorial [1]_. The examples
19+are presented are tested with Idris and can be found in the
20+examples directory of the Idris repository.
21+
22+Consider, for example, the following introductory function which
23+illustrates the kind of properties which can be expressed in the type
24+system:
25+
26+.. code-block:: idris
27+
28+ vadd : Vect n Int -> Vect n Int -> Vect n Int
29+ vadd [] [] = []
30+ vadd (x :: xs) (y :: ys) = x + y :: vadd xs ys
31+
32+This function adds corresponding elements in a pair of vectors. The type
33+guarantees that the vectors will contain only elements of type ``Int``,
34+and that the input lengths and the output length all correspond. A
35+natural question to ask here, which is typically neglected by
36+introductory tutorials, is “How do I turn this into a program?” That is,
37+given some lists entered by a user, how do we get into a position to be
38+able to apply the ``vadd`` function? Before doing so, we will have to:
39+
40+- Read user input, either from the keyboard, a file, or some other
41+ input device.
42+
43+- Check that the user inputs are valid, i.e. contain only ``Int`` s
44+ and are the same length, and report an error if not.
45+
46+- Write output
47+
48+The complete program will include side-effects for I/O and error
49+handling, before we can get to the pure core functionality. In this
50+tutorial, we will see how Idris supports side-effects.
51+Furthermore, we will see how we can use the dependent type system to
52+*reason* about stateful and side-effecting programs. We will return to
53+this specific example later.
54+
55+Hello world
56+===========
57+
58+To give an idea of how programs with effects look in , here is the
59+ubiquitous “Hello world” program, written using the ``Effects``
60+library:
61+
62+.. code-block:: idris
63+
64+ module Main
65+
66+ import Effects
67+ import Effect.StdIO
68+
69+ hello : [STDIO] Eff ()
70+ hello = putStrLn “Hello world!”
71+
72+ main : IO ()
73+ main = run hello
74+
75+As usual, the entry point is ``main``. All ``main`` has to do is invoke the
76+``hello`` function which supports the ``STDIO`` effect for console I/O, and
77+returns the unit value. All programs using the ``Effects`` library must
78+``import Effects``. The details of the ``Eff`` type will be presented in the
79+remainder of this tutorial.
80+
81+To compile and run this program, Idris needs to be told to include
82+the ``Effects`` package, using the ``-p effects`` flag (this flag is
83+required for all examples in this tutorial):
84+
85+.. code-block:: sh
86+
87+ idris hello.idr -o hello -p effects
88+ ./hello Hello world!
89+
90+Outline
91+=======
92+
93+The tutorial is structured as follows: first, in Section
94+:ref:`sect-state`, we will discuss state management, describing why it
95+is important and introducing the ``effects`` library to show how it
96+can be used to manage state. This section also gives an overview of
97+the syntax of effectful programs. Section :ref:`sect-simpleff` then
98+introduces a number of other effects a program may have: I/O;
99+Exceptions; Random Numbers; and Non-determinism, giving examples for
100+each, and an extended example combining several effects in one
101+complete program. Section :ref:`sect-depeff` introduces *dependent*
102+effects, showing how states and resources can be managed in
103+types. Section :ref:`sect-impleff` shows how new effects can be
104+implemented. Section :ref:`sect-hangman` gives an extended example
105+showing how to implement a “mystery word” guessing game, using effects
106+to describe the rules of the game and ensure they are implemented
107+accurately. References to further reading are given in Section
108+:ref:`sect-further`.
109+
110+.. [1]
111+ You do not, however, need to know what a monad is. A correctness
112+ property of this tutorial is that the word “monad” should appear
113+ exactly twice, both in this footnote.
docs/effects/simpleeff.rstnew file+592
@@ -0,0 +1,592 @@
1+.. _sect-simpleff:
2+
3+==============
4+Simple Effects
5+==============
6+
7+So far we have seen how to write programs with locally mutable state
8+using the ``STATE`` effect. To recap, we have the definitions below
9+in a module ``Effect.State``
10+
11+.. code-block:: idris
12+
13+ module Effect.State
14+
15+ STATE : Type -> EFFECT
16+
17+ get : { [STATE x] } Eff x
18+ put : x -> { [STATE x] } Eff ()
19+ putM : y -> { [STATE x] ==> [STATE y] } Eff ()
20+ update : (x -> x) -> { [STATE x] } Eff ()
21+
22+ instance Handler State m
23+
24+The last line, ``instance Handler State m``, means that the ``STATE``
25+effect is usable in any computation context ``m``. That is, a program
26+which uses this effect and returns something of type ``a`` can be
27+evaluated to something of type ``m a`` using ``run``, for any
28+``m``. The lower case ``State`` is a data type describing the
29+operations which make up the ``STATE`` effect itself—we will go into
30+more detail about this in Section :ref:`sect-impleff`.
31+
32+In this section, we will introduce some other supported effects,
33+allowing console I/O, exceptions, random number generation and
34+non-deterministic programming. For each effect we introduce, we will
35+begin with a summary of the effect, its supported operations, and the
36+contexts in which it may be used, like that above for ``STATE``, and
37+go on to present some simple examples. At the end, we will see some
38+examples of programs which combine multiple effects.
39+
40+All of the effects in the library, including those described in this
41+section, are summarised in Appendix :ref:`sect-appendix`.
42+
43+Console I/O
44+-----------
45+
46+Console I/O is supported with the ``STDIO``
47+effect, which allows reading and writing characters and strings to and
48+from standard input and standard output. Notice that there is a
49+constraint here on the computation context ``m``, because it only
50+makes sense to support console I/O operations in a context where we
51+can perform (or at the very least simulate) console I/O:
52+
53+.. code-block:: idris
54+
55+ module Effect.StdIO
56+
57+ STDIO : EFFECT
58+
59+ putChar : Char -> { [STDIO] } Eff ()
60+ putStr : String -> { [STDIO] } Eff ()
61+ putStrLn : String -> { [STDIO] } Eff ()
62+
63+ getStr : { [STDIO] } Eff String
64+ getChar : { [STDIO] } Eff Char
65+
66+ instance Handler StdIO IO
67+ instance Handler StdIO (IOExcept a)
68+
69+Examples
70+~~~~~~~~
71+
72+A program which reads the user’s name, then says hello, can be written
73+as follows:
74+
75+.. code-block:: idris
76+
77+ hello : { [STDIO] } Eff ()
78+ hello = do putStr "Name? "
79+ x <- getStr
80+ putStrLn ("Hello " ++ trim x ++ "!")
81+
82+We use ``trim`` here to remove the trailing newline from the
83+input. The resource associated with ``STDIO`` is simply the empty
84+tuple, which has a default value ``()``, so we can run this as
85+follows:
86+
87+.. code-block:: idris
88+
89+ main : IO ()
90+ main = run hello
91+
92+In ``hello`` we could also use ``!``-notation instead of ``x <-
93+getStr``, since we only use the string that is read once:
94+
95+.. code-block:: idris
96+
97+ hello : { [STDIO] } Eff ()
98+ hello = do putStr "Name? "
99+ putStrLn ("Hello " ++ trim !getStr ++ "!")
100+
101+More interestingly, we can combine multiple effects in one
102+program. For example, we can loop, counting the number of people we’ve
103+said hello to:
104+
105+.. code-block:: idris
106+
107+ hello : { [STATE Int, STDIO] } Eff ()
108+ hello = do putStr "Name? "
109+ putStrLn ("Hello " ++ trim !getStr ++ "!")
110+ update (+1)
111+ putStrLn ("I've said hello to: " ++ show !get ++ " people")
112+ hello
113+
114+The list of effects given in ``hello`` means that the function can
115+call ``get`` and ``put`` on an integer state, and any functions which
116+read and write from the console. To run this, ``main`` does not need
117+to be changed.
118+
119+Aside: Resource Types
120+~~~~~~~~~~~~~~~~~~~~~
121+
122+To find out the resource type of an effect, if necessary (for example
123+if we want to initialise a resource explicitiy with ``runInit`` rather
124+than using a default value with ``run``) we can run the
125+``resourceType`` function at the REPL:
126+
127+.. code-block:: idris
128+
129+ *ConsoleIO> resourceType STDIO
130+ () : Type
131+ *ConsoleIO> resourceType (STATE Int)
132+ Int : Type
133+
134+Exceptions
135+----------
136+
137+The ``EXCEPTION``
138+effect is declared in module ``Effect.Exception``. This allows programs
139+to exit immediately with an error, or errors to be handled more
140+generally:
141+
142+.. _eff-exception:
143+.. code-block:: idris
144+
145+ module Effect.Exception
146+
147+ EXCEPTION : Type -> EFFECT
148+
149+ raise : a -> { [EXCEPTION a ] } Eff b
150+
151+ instance Handler (Exception a) Maybe
152+ instance Handler (Exception a) List
153+ instance Handler (Exception a) (Either a)
154+ instance Handler (Exception a) (IOExcept a)
155+ instance Show a => Handler (Exception a) IO
156+
157+Example
158+~~~~~~~
159+
160+Suppose we have a ``String`` which is expected to represent an integer
161+in the range ``0`` to ``n``. We can write a function ``parseNumber``
162+which returns an ``Int`` if parsing the string returns a number in the
163+appropriate range, or throws an exception otherwise. Exceptions are
164+paramaterised by an error type:
165+
166+.. code-block:: idris
167+
168+ data Err = NotANumber | OutOfRange
169+
170+ parseNumber : Int -> String -> { [EXCEPTION Err] } Eff Int
171+ parseNumber num str
172+ = if all isDigit (unpack str)
173+ then let x = cast str in
174+ if (x >=0 && x <= num)
175+ then pure x
176+ else raise OutOfRange
177+ else raise NotANumber
178+
179+Programs which support the ``EXCEPTION`` effect can be run in any
180+context which has some way of throwing errors, for example, we can run
181+``parseNumber`` in the ``Either Err`` context. It returns a value of
182+the form ``Right x`` if successful:
183+
184+.. code-block:: idris
185+
186+ *Exception> the (Either Err Int) $ run (parseNumber 42 "20")
187+ Right 20 : Either Err Int
188+
189+Or ``Left e`` on failure, carrying the appropriate exception:
190+
191+.. code-block:: idris
192+
193+ *Exception> the (Either Err Int) $ run (parseNumber 42 "50")
194+ Left OutOfRange : Either Err Int
195+
196+ *Exception> the (Either Err Int) $ run (parseNumber 42 "twenty")
197+ Left NotANumber : Either Err Int
198+
199+In fact, we can do a little bit better with ``parseNumber``, and have
200+it return a *proof* that the integer is in the required range along
201+with the integer itself. One way to do this is define a type of
202+bounded integers, ``Bounded``:
203+
204+.. code-block:: idris
205+
206+ Bounded : Int -> Type
207+ Bounded x = (n : Int ** So (n >= 0 && n <= x))
208+
209+Recall that ``So`` is parameterised by a ``Bool``, and only ``So
210+True`` is inhabited. We can use ``choose`` to construct such a value
211+from the result of a dynamic check:
212+
213+.. code-block:: idris
214+
215+ data So : Bool -> Type = Oh : So True
216+
217+ choose : (b : Bool) -> Either (So b) (So (not b))
218+
219+We then write ``parseNumber`` using ``choose`` rather than an
220+``if/then/else`` construct, passing the proof it returns on success as
221+the boundedness proof:
222+
223+.. code-block:: idris
224+
225+ parseNumber : (x : Int) -> String -> { [EXCEPTION Err] } Eff (Bounded x)
226+ parseNumber x str
227+ = if all isDigit (unpack str)
228+ then let num = cast str in
229+ case choose (num >=0 && num <= x) of
230+ Left p => pure (num ** p)
231+ Right p => raise OutOfRange
232+ else raise NotANumber
233+
234+Random Numbers
235+--------------
236+
237+Random number generation is also implemented by the library, in module
238+``Effect.Random``:
239+
240+.. code-block:: idris
241+
242+ module Effect.Random
243+
244+ RND : EFFECT
245+
246+ srand : Integer -> { [RND] } Eff ()
247+ rndInt : Integer -> Integer -> { [RND] } Eff Integer
248+ rndFin : (k : Nat) -> { [RND] } Eff (Fin (S k))
249+
250+ instance Handler Random m
251+
252+Random number generation is considered side-effecting because its
253+implementation generally relies on some external source of randomness.
254+The default implementation here relies on an integer *seed*, which can
255+be set with ``srand``. A specific seed will lead to a predictable,
256+repeatable sequence of random numbers. There are two functions which
257+produce a random number:
258+
259+- ``rndInt``, which returns a random integer between the given lower
260+ and upper bounds.
261+
262+- ``rndFin``, which returns a random element of a finite set
263+ (essentially a number with an upper bound given in its type).
264+
265+Example
266+~~~~~~~
267+
268+We can use the ``RND`` effect to implement a simple guessing game. The
269+``guess`` function, given a target number, will repeatedly ask the
270+user for a guess, and state whether the guess is too high, too low, or
271+correct:
272+
273+.. code-block:: idris
274+
275+ guess : Int -> { [STDIO] } Eff ()
276+
277+For reference, the code for ``guess`` is given below:
278+
279+.. _eff-game:
280+.. code-block:: idris
281+
282+ guess : Int -> { [STDIO] } Eff ()
283+ guess target
284+ = do putStr "Guess: "
285+ case run {m=Maybe} (parseNumber 100 (trim !getStr)) of
286+ Nothing => do putStrLn "Invalid input"
287+ guess target
288+ Just (v ** _) =>
289+ case compare v target of
290+ LT => do putStrLn "Too low"
291+ guess target
292+ EQ => putStrLn "You win!"
293+ GT => do putStrLn "Too high"
294+ guess target
295+
296+Note that we use ``parseNumber`` as defined previously to read user input, but
297+we don’t need to list the ``EXCEPTION`` effect because we use a nested ``run``
298+to invoke ``parseNumber``, independently of the calling effectful program.
299+
300+To invoke this, we pick a random number within the range 0–100,
301+having set up the random number generator with a seed, then run
302+``guess``:
303+
304+.. code-block:: idris
305+
306+ game : { [RND, STDIO] } Eff ()
307+ game = do srand 123456789
308+ guess (fromInteger !(rndInt 0 100))
309+
310+ main : IO ()
311+ main = run game
312+
313+If no seed is given, it is set to the ``default`` value. For a less
314+predictable game, some better source of randomness would be required,
315+for example taking an initial seed from the system time. To see how to
316+do this, see the ``SYSTEM`` effect described in :ref:`sect-appendix`.
317+
318+
319+Non-determinism
320+---------------
321+
322+The listing below gives the definition of the non-determinism
323+effect, which allows a program to choose a value non-deterministically
324+from a list of possibilities in such a way that the entire computation
325+succeeds:
326+
327+.. code-block:: idris
328+
329+ import Effects
330+ import Effect.Select
331+
332+ SELECT : EFFECT
333+
334+ select : List a -> { [SELECT] } Eff a
335+
336+ instance Handler Selection Maybe
337+ instance Handler Selection List
338+
339+Example
340+~~~~~~~
341+
342+The ``SELECT`` effect can be used to solve constraint problems, such
343+as finding Pythagorean triples. The idea is to use ``select`` to give
344+a set of candidate values, then throw an exception for any combination
345+of values which does not satisfy the constraint:
346+
347+.. code-block:: idris
348+
349+ triple : Int -> { [SELECT, EXCEPTION String] } Eff (Int, Int, Int)
350+ triple max = do z <- select [1..max]
351+ y <- select [1..z]
352+ x <- select [1..y]
353+ if (x * x + y * y == z * z)
354+ then pure (x, y, z)
355+ else raise "No triple"
356+
357+This program chooses a value for ``z`` between ``1`` and ``max``, then
358+values for ``y`` and ``x``. In operation, after a ``select``, the
359+program executes the rest of the ``do``-block for every possible
360+assignment, effectively searching depth-first. If the list is empty
361+(or an exception is thrown) execution fails.
362+
363+There are handlers defined for ``Maybe`` and ``List`` contexts, i.e.
364+contexts which can capture failure. Depending on the context ``m``,
365+``triple`` will either return the first triple it finds (if in
366+``Maybe`` context) or all triples in the range (if in ``List``
367+context). We can try this as follows:
368+
369+.. code-block:: idris
370+
371+ main : IO ()
372+ main = do print $ the (Maybe _) $ run (triple 100)
373+ print $ the (List _) $ run (triple 100)
374+
375+``vadd`` revisited
376+------------------
377+
378+We now return to the ``vadd`` program from the introduction. Recall the
379+definition:
380+
381+.. code-block:: idris
382+
383+ vadd : Vect n Int -> Vect n Int -> Vect n Int
384+ vadd [] [] = []
385+ vadd (x :: idris xs) (y :: ys) = x + y :: vadd xs ys
386+
387+Using , we can set up a program so that it reads input from a user,
388+checks that the input is valid (i.e both vectors contain integers, and
389+are the same length) and if so, pass it on to ``vadd``. First, we
390+write a wrapper for ``vadd`` which checks the lengths and throw an
391+exception if they are not equal. We can do this for input vectors of
392+length ``n`` and ``m`` by matching on the implicit arguments ``n`` and
393+``m`` and using ``decEq`` to produce a proof of their equality, if
394+they are equal:
395+
396+.. code-block:: idris
397+
398+ vadd_check : Vect n Int -> Vect m Int ->
399+ { [EXCEPTION String] } Eff (Vect m Int)
400+ vadd_check {n} {m} xs ys with (decEq n m)
401+ vadd_check {n} {m=n} xs ys | (Yes Refl) = pure (vadd xs ys)
402+ vadd_check {n} {m} xs ys | (No contra) = raise "Length mismatch"
403+
404+To read a vector from the console, we implement a function of the
405+following type:
406+
407+.. code-block:: idris
408+
409+ read_vec : { [STDIO] } Eff (p ** Vect p Int)
410+
411+This returns a dependent pair of a length, and a vector of that
412+length, because we cannot know in advance how many integers the user
413+is going to input. One way to implement this function, using ``-1`` to
414+indicate the end of input, is shown in Listing [readvec]. This uses a
415+variation on ``parseNumber`` which does not require a number to be
416+within range.
417+
418+Finally, we write a program which reads two vectors and prints the
419+result of pairwise addition of them, throwing an exception if the
420+inputs are of differing lengths:
421+
422+.. code-block:: idris
423+
424+ do_vadd : { [STDIO, EXCEPTION String] } Eff ()
425+ do_vadd = do putStrLn "Vector 1"
426+ (_ ** xs) <- read_vec
427+ putStrLn "Vector 2"
428+ (_ ** ys) <- read_vec
429+ putStrLn (show !(vadd_check xs ys))
430+
431+By having explicit lengths in the type, we can be sure that ``vadd``
432+is only being used where the lengths of inputs are guaranteed to be
433+equal. This does not stop us reading vectors from user input, but it
434+does require that the lengths are checked and any discrepancy is dealt
435+with gracefully.
436+
437+.. code-block:: idris
438+
439+ read_vec : { [STDIO] } Eff (p ** Vect p Int)
440+ read_vec = do putStr "Number (-1 when done): "
441+ case run (parseNumber (trim !getStr)) of
442+ Nothing => do putStrLn "Input error"
443+ read_vec
444+ Just v => if (v /= -1)
445+ then do (_ ** xs) <- read_vec
446+ pure (_ ** v :: xs)
447+ else pure (_ ** [])
448+ where
449+ parseNumber : String -> { [EXCEPTION String] } Eff Int
450+ parseNumber str
451+ = if all (\x => isDigit x || x == '-') (unpack str)
452+ then pure (cast str)
453+ else raise "Not a number"
454+
455+Example: An Expression Calculator
456+---------------------------------
457+
458+To show how these effects can fit together, let us consider an
459+evaluator for a simple expression language, with addition and integer
460+values.
461+
462+.. code-block:: idris
463+
464+ data Expr = Val Integer
465+ | Add Expr Expr
466+
467+An evaluator for this language always returns an ``Integer``, and
468+there are no situations in which it can fail!
469+
470+.. code-block:: idris
471+
472+ eval : Expr -> Integer
473+ eval (Val x) = x
474+ eval (Add l r) = eval l + eval r
475+
476+If we add variables, however, things get more interesting. The
477+evaluator will need to be able to access the values stored in
478+variables, and variables may be undefined.
479+
480+.. code-block:: idris
481+
482+ data Expr = Val Integer
483+ | Var String
484+ | Add Expr Expr
485+
486+To start, we will change the type of ``eval`` so that it is effectful,
487+and supports an exception effect for throwing errors, and a state
488+containing a mapping from variable names (as ``String``) to their
489+values:
490+
491+.. code-block:: idris
492+
493+ Env : Type
494+ Env = List (String, Integer)
495+
496+ eval : Expr -> { [EXCEPTION String, STATE Env] } Eff Integer
497+ eval (Val x) = return x
498+ eval (Add l r) = return $ !(eval l) + !(eval r)
499+
500+Note that we are using ``!``-notation to avoid having to bind
501+subexpressions in a ``do`` block. Next, we add a case for evaluating
502+``Var``:
503+
504+.. code-block:: idris
505+
506+ eval (Var x) = case lookup x !get of
507+ Nothing => raise $ "No such variable " ++ x
508+ Just val => return val
509+
510+This retrieves the state (with ``get``, supported by the ``STATE Env``
511+effect) and raises an exception if the variable is not in the
512+environment (with ``raise``, supported by the ``EXCEPTION String``
513+effect).
514+
515+To run the evaluator on a particular expression in a particular
516+environment of names and their values, we can write a function which
517+sets the state then invokes ``eval``:
518+
519+.. code-block:: idris
520+
521+ runEval : List (String, Integer) -> Expr -> Maybe Integer
522+ runEval args expr = run (eval' expr)
523+ where eval' : Expr -> { [EXCEPTION String, STATE Env] } Eff Integer
524+ eval' e = do put args
525+ eval e
526+
527+We have picked ``Maybe`` as a computation context here; it needs to be
528+a context which is available for every effect supported by
529+``eval``. In particular, because we have exceptions, it needs to be a
530+context which supports exceptions. Alternatively, ``Either String`` or
531+``IO`` would be fine, for example.
532+
533+What if we want to extend the evaluator further, with random number
534+generation? To achieve this, we add a new constructor to ``Expr``,
535+which gives a random number up to a maximum value:
536+
537+.. code-block:: idris
538+
539+ data Expr = Val Integer
540+ | Var String
541+ | Add Expr Expr
542+ | Random Integer
543+
544+Then, we need to deal with the new case, making sure that we extend
545+the list of events to include ``RND``. It doen’t matter where ``RND``
546+appears in the list, as long as it is present:
547+
548+.. code-block:: idris
549+
550+ eval : Expr -> { [EXCEPTION String, RND, STATE Env] } Eff Integer
551+
552+ eval (Random upper) = rndInt 0 upper
553+
554+For test purposes, we might also want to print the random number which
555+has been generated:
556+
557+.. code-block:: idris
558+
559+ eval (Random upper) = do val <- rndInt 0 upper
560+ putStrLn (show val)
561+ return val
562+
563+If we try this without extending the effects list, we would see an
564+error something like the following:
565+
566+::
567+
568+ Expr.idr:28:6:When elaborating right hand side of eval:
569+ Can't solve goal
570+ SubList [STDIO]
571+ [(EXCEPTION String), RND, (STATE (List (String, Integer)))]
572+
573+In other words, the ``STDIO`` effect is not available. We can correct
574+this simply by updating the type of ``eval`` to include ``STDIO``.
575+
576+.. code-block:: idris
577+
578+ eval : Expr -> { [STDIO, EXCEPTION String, RND, STATE Env] } Eff Integer
579+
580+Note that using ``STDIO`` will restrict the number of contexts in
581+which ``eval`` can be ``run`` to those which support ``STDIO``, such
582+as ``IO``. Once effect lists get longer, it can be a good idea instead
583+to encapsulate sets of effects in a type synonym. This is achieved as
584+follows, simply by defining a function which computes a type, since
585+types are first class in Idris:
586+
587+.. code-block:: idris
588+
589+ EvalEff : Type -> Type
590+ EvalEff t = { [STDIO, EXCEPTION String, RND, STATE Env] } Eff t
591+
592+ eval : Expr -> EvalEff Integer
docs/effects/state.rstnew file+519
@@ -0,0 +1,519 @@
1+.. _sect-state:
2+
3+=====
4+State
5+=====
6+
7+Many programs, even pure programs, can benefit from locally mutable
8+state. For example, consider a program which tags binary tree nodes
9+with a counter, by an inorder traversal (i.e. counting depth first,
10+left to right). This would perform something like the following:
11+
12+|image|
13+
14+We can describe binary trees with the following data type ``BTree``
15+and ``testTree`` to represent the example input above:
16+
17+.. code-block:: idris
18+
19+ data BTree a = Leaf
20+ | Node (BTree a) a (BTree a)
21+
22+ testTree : BTree String
23+ testTree = Node (Node Leaf "Jim" Leaf)
24+ "Fred"
25+ (Node (Node Leaf "Alice" Leaf)
26+ "Sheila"
27+ (Node Leaf "Bob" Leaf))
28+
29+Then our function to implement tagging, beginning to tag with a
30+specific value ``i``, has the following type:
31+
32+.. code-block:: idris
33+
34+ treeTag : (i : Int) -> BTree a -> BTree (Int, a)
35+
36+First attempt
37+-------------
38+
39+Naïvely, we can implement ``treeTag`` by implementing a helper
40+function which propagates a counter, returning the result of the count
41+for each subtree:
42+
43+.. code-block:: idris
44+
45+ treeTagAux : (i : Int) -> BTree a -> (Int, BTree (Int, a))
46+ treeTagAux i Leaf = (i, Leaf)
47+ treeTagAux i (Node l x r)
48+ = let (i', l') = treeTagAux i l in
49+ let x' = (i', x) in
50+ let (i'', r') = treeTagAux (i' + 1) r in
51+ (i'', Node l' x' r')
52+
53+ treeTag : (i : Int) -> BTree a -> BTree (Int, a)
54+ treeTag i x = snd (treeTagAux i x)
55+
56+This gives the expected result when run at the REPL prompt:
57+
58+.. code-block:: idris
59+
60+ *TreeTag> treeTag 1 testTree
61+ Node (Node Leaf (1, "Jim") Leaf)
62+ (2, "Fred")
63+ (Node (Node Leaf (3, "Alice") Leaf)
64+ (4, "Sheila")
65+ (Node Leaf (5, "Bob") Leaf)) : BTree (Int, String)
66+
67+This works as required, but there are several problems when we try to
68+scale this to larger programs. It is error prone, because we need to
69+ensure that state is propagated correctly to the recursive calls (i.e.
70+passing the appropriate ``i`` or ``i’``). It is hard to read, because
71+the functional details are obscured by the state propagation. Perhaps
72+most importantly, there is a common programming pattern here which
73+should be abstracted but instead has been implemented by hand. There
74+is local mutable state (the counter) which we have had to make
75+explicit.
76+
77+Introducing ``Effects``
78+-----------------------
79+
80+Idris provides a library, ``Effects`` [3]_, which captures this
81+pattern and many others involving effectful computation [1]_. An
82+effectful program ``f`` has a type of the following form:
83+
84+.. code-block:: idris
85+
86+ f : (x1 : a1) -> (x2 : a2) -> ... -> { effs } Eff t
87+
88+That is, the return type gives the effects that ``f`` supports
89+(``effs``, of type ``List EFFECT``) and the type the computation
90+returns ``t``. So, our ``treeTagAux`` helper could be written with the
91+following type:
92+
93+.. code-block:: idris
94+
95+ treeTagAux : BTree a -> { [STATE Int] } Eff (BTree (Int, a))
96+
97+That is, ``treeTagAux`` has access to an integer state, because the
98+list of available effects includes ``STATE Int``. ``STATE`` is
99+declared as follows in the module ``Effect.State`` (that is, we must
100+``import Effect.State`` to be able to use it):
101+
102+.. code-block:: idris
103+
104+ STATE : Type -> EFFECT
105+
106+It is an effect parameterised by a type (by convention, we write
107+effects in all capitals). The ``treeTagAux`` function is an effectful
108+program which builds a new tree tagged with ``Ints``, and is
109+implemented as follows:
110+
111+.. code-block:: idris
112+
113+ treeTagAux Leaf = pure Leaf
114+ treeTagAux (Node l x r)
115+ = do l' <- treeTagAux l
116+ i <- get
117+ put (i + 1)
118+ r' <- treeTagAux r
119+ pure (Node l' (i, x) r')
120+
121+There are several remarks to be made about this implementation.
122+Essentially, it hides the state, which can be accessed using ``get``
123+and updated using ``put``, but it introduces several new features.
124+Specifically, it uses ``do``-notation, binding variables with ``<-``,
125+and a ``pure`` function. There is much to be said about these
126+features, but for our purposes, it suffices to know the following:
127+
128+- ``do`` blocks allow effectful operations to be sequenced.
129+
130+- ``x <- e`` binds the result of an effectful operation ``e`` to a
131+ variable ``x``. For example, in the above code, ``treeTagAux l`` is
132+ an effectful operation returning ``BTree (Int, a)``, so ``l’`` has
133+ type ``BTree (Int, a)``.
134+
135+- ``pure e`` turns a pure value ``e`` into the result of an effectful
136+ operation.
137+
138+The ``get`` and ``put`` functions read and write a state ``t``,
139+assuming that the ``STATE t`` effect is available. They have the
140+following types, polymorphic in the state ``t`` they manage:
141+
142+.. code-block:: idris
143+
144+ get : { [STATE t] } Eff t
145+ put : t -> { [STATE t] } Eff ()
146+
147+A program in ``Eff`` can call any other function in ``Eff`` provided
148+that the calling function supports at least the effects required by
149+the called function. In this case, it is valid for ``treeTagAux`` to
150+call both ``get`` and ``put`` because all three functions support the
151+``STATE Int`` effect.
152+
153+Programs in ``Eff`` are run in some underlying *computation context*,
154+using the ``run`` or ``runPure`` function. Using ``runPure``, which
155+runs an effectful program in the identity context, we can write the
156+``treeTag`` function as follows, using ``put`` to initialise the
157+state:
158+
159+.. code-block:: idris
160+
161+ treeTag : (i : Int) -> BTree a -> BTree (Int, a)
162+ treeTag i x = runPure (do put i
163+ treeTagAux x)
164+
165+We could also run the program in an impure context such as ``IO``,
166+without changing the definition of ``treeTagAux``, by using ``run``
167+instead of ``runPure``:
168+
169+.. code-block:: idris
170+
171+ treeTagAux : BTree a -> { [STATE Int] } Eff (BTree (Int, a))
172+ ...
173+
174+ treeTag : (i : Int) -> BTree a -> IO (BTree (Int, a))
175+ treeTag i x = run (do put i
176+ treeTagAux x)
177+
178+Note that the definition of ``treeTagAux`` is exactly as before. For
179+reference, this complete program (including a ``main`` to run it) is
180+shown in Listing [introprog].
181+
182+.. code-block:: idris
183+
184+ module Main
185+
186+ import Effects
187+ import Effect.State
188+
189+ data BTree a = Leaf
190+ | Node (BTree a) a (BTree a)
191+
192+ instance Show a => Show (BTree a) where
193+ show Leaf = "[]"
194+ show (Node l x r) = "[" ++ show l ++ " "
195+ ++ show x ++ " "
196+ ++ show r ++ "]"
197+
198+ testTree : BTree String
199+ testTree = Node (Node Leaf "Jim" Leaf)
200+ "Fred"
201+ (Node (Node Leaf "Alice" Leaf)
202+ "Sheila"
203+ (Node Leaf "Bob" Leaf))
204+
205+ treeTagAux : BTree a -> { [STATE Int] } Eff (BTree (Int, a))
206+ treeTagAux Leaf = pure Leaf
207+ treeTagAux (Node l x r) = do l' <- treeTagAux l
208+ i <- get
209+ put (i + 1)
210+ r' <- treeTagAux r
211+ pure (Node l' (i, x) r')
212+
213+ treeTag : (i : Int) -> BTree a -> BTree (Int, a)
214+ treeTag i x = runPure (do put i; treeTagAux x)
215+
216+ main : IO ()
217+ main = print (treeTag 1 testTree)
218+
219+Effects and Resources
220+---------------------
221+
222+Each effect is associated with a *resource*, which is initialised
223+before an effectful program can be run. For example, in the case of
224+``STATE Int`` the corresponding resource is the integer state itself.
225+The types of ``runPure`` and ``run`` show this (slightly simplified
226+here for illustrative purposes):
227+
228+.. code-block:: idris
229+
230+ runPure : {env : Env id xs} -> { xs } Eff a -> a
231+ run : Applicative m => {env : Env m xs} -> { xs } Eff a -> m a
232+
233+The ``env`` argument is implicit, and initialised automatically where
234+possible using default values given by instances of the following type
235+class:
236+
237+.. code-block:: idris
238+
239+ class Default a where
240+ default : a
241+
242+Instances of ``Default`` are defined for all primitive types, and many
243+library types such as ``List``, ``Vect``, ``Maybe``, pairs, etc.
244+However, where no default value exists for a resource type (for
245+example, you may want a ``STATE`` type for which there is no
246+``Default`` instance) the resource environment can be given explicitly
247+using one of the following functions:
248+
249+.. code-block:: idris
250+
251+ runPureInit : Env id xs -> { xs } Eff a -> a
252+ runInit : Applicative m => Env m xs -> { xs } Eff a -> m a
253+
254+To be well-typed, the environment must contain resources corresponding
255+exactly to the effects in ``xs``. For example, we could also have
256+implemented ``treeTag`` by initialising the state as follows:
257+
258+.. code-block:: idris
259+
260+ treeTag : (i : Int) -> BTree a -> BTree (Int, a)
261+ treeTag i x = runPureInit [i] (treeTagAux x)
262+
263+Labelled Effects
264+----------------
265+
266+What if we have more than one state, especially more than one state of
267+the same type? How would ``get`` and ``put`` know which state they
268+should be referring to? For example, how could we extend the tree
269+tagging example such that it additionally counts the number of leaves
270+in the tree? One possibility would be to change the state so that it
271+captured both of these values, e.g.:
272+
273+.. code-block:: idris
274+
275+ treeTagAux : BTree a
276+ -> { [STATE (Int, Int)] } Eff (BTree (Int, a))
277+
278+Doing this, however, ties the two states together throughout (as well
279+as not indicating which integer is which). It would be nice to be able
280+to call effectful programs which guaranteed only to access one of the
281+states, for example. In a larger application, this becomes
282+particularly important.
283+
284+The library therefore allows effects in general to be *labelled* so
285+that they can be referred to explicitly by a particular name. This
286+allows multiple effects of the same type to be included. We can count
287+leaves and update the tag separately, by labelling them as follows:
288+
289+.. code-block:: idris
290+
291+ treeTagAux : BTree a
292+ -> {['Tag ::: STATE Int,
293+ 'Leaves ::: STATE Int]} Eff (BTree (Int, a))
294+
295+The ``:::`` operator allows an arbitrary label to be given to an
296+effect. This label can be any type—it is simply used to identify an
297+effect uniquely. Here, we have used a symbol type. In general
298+``’name`` introduces a new symbol, the only purpose of which is to
299+disambiguate values [2]_.
300+
301+When an effect is labelled, its operations are also labelled using the
302+``:-`` operator. In this way, we can say explicitly which state we
303+mean when using ``get`` and ``put``. The tree tagging program which
304+also counts leaves can be written as follows:
305+
306+.. code-block:: idris
307+
308+ treeTagAux Leaf = do
309+ 'Leaves :- update (+1)
310+ pure Leaf
311+ treeTagAux (Node l x r) = do
312+ l' <- treeTagAux l
313+ i <- 'Tag :- get
314+ 'Tag :- put (i + 1)
315+ r' <- treeTagAux r
316+ pure (Node l' (i, x) r')
317+
318+The ``update`` function here is a combination of ``get`` and ``put``,
319+applying a function to the current state.
320+
321+.. code-block:: idris
322+
323+ update : (x -> x) -> { [STATE x] } Eff ()
324+
325+Finally, our top level ``treeTag`` function now returns a pair of the
326+number of leaves, and the new tree. Resources for labelled effects are
327+intialised using the ``:=`` operator (reminisicent of assignment in an
328+imperative language):
329+
330+.. code-block:: idris
331+
332+ treeTag : (i : Int) -> BTree a -> (Int, BTree (Int, a))
333+ treeTag i x = runPureInit ['Tag := i, 'Leaves := 0]
334+ (do x' <- treeTagAux x
335+ leaves <- 'Leaves :- get
336+ pure (leaves, x'))
337+
338+To summarise, we have:
339+
340+- ``:::`` to convert an effect to a labelled effect.
341+
342+- ``:-`` to convert an effectful operation to a labelled effectful
343+ operation.
344+
345+- ``:=`` to initialise a resource for a labelled effect.
346+
347+Or, more formally with their types (slightly simplified to account
348+only for the situation where available effects are not updated):
349+
350+.. code-block:: idris
351+
352+ (:::) : lbl -> EFFECT -> EFFECT
353+ (:-) : (l : lbl) -> { [x] } Eff a -> { [l ::: x] } Eff a
354+ (:=) : (l : lbl) -> res -> LRes l res
355+
356+Here, ``LRes`` is simply the resource type associated with a labelled
357+effect. Note that labels are polymorphic in the label type ``lbl``.
358+Hence, a label can be anything—a string, an integer, a type, etc.
359+
360+``!``-notation
361+--------------
362+
363+In many cases, using ``do``-notation can make programs unnecessarily
364+verbose, particularly in cases where the value bound is used once,
365+immediately. The following program returns the length of the
366+``String`` stored in the state, for example:
367+
368+.. code-block:: idris
369+
370+ stateLength : { [STATE String] } Eff Nat
371+ stateLength = do x <- get
372+ pure (length x)
373+
374+This seems unnecessarily verbose, and it would be nice to program in a
375+more direct style in these cases. provides ``!``-notation to help with
376+this. The above program can be written instead as:
377+
378+.. code-block:: idris
379+
380+ stateLength : { [STATE String] } Eff Nat
381+ stateLength = pure (length !get)
382+
383+The notation ``!expr`` means that the expression ``expr`` should be
384+evaluated and then implicitly bound. Conceptually, we can think of
385+``!`` as being a prefix function with the following type:
386+
387+.. code-block:: idris
388+
389+ (!) : { xs } Eff a -> a
390+
391+Note, however, that it is not really a function, merely syntax! In
392+practice, a subexpression ``!expr`` will lift ``expr`` as high as
393+possible within its current scope, bind it to a fresh name ``x``, and
394+replace ``!expr`` with ``x``. Expressions are lifted depth first, left
395+to right. In practice, ``!``-notation allows us to program in a more
396+direct style, while still giving a notational clue as to which
397+expressions are effectful.
398+
399+For example, the expression:
400+
401+.. code-block:: idris
402+
403+ let y = 42 in f !(g !(print y) !x)
404+
405+is lifted to:
406+
407+.. code-block:: idris
408+
409+ let y = 42 in do y' <- print y
410+ x' <- x
411+ g' <- g y' x'
412+ f g'
413+
414+Syntactic Sugar and ``Eff``
415+---------------------------
416+
417+By now, you may be wondering about the syntax we are using for
418+``Eff``, because it doesn’t look like a normal type! (If not, you may
419+safely skip this section and return to it later.) In fact, the type of
420+``Eff`` is the following:
421+
422+.. code-block:: idris
423+
424+ Eff : (x : Type) ->
425+ List EFFECT -> (x -> List EFFECT) -> Type
426+
427+This is more general than the types we have been writing so far. It is
428+parameterised over a result type ``x``, as we have already seen, but
429+also a ``List EFFECT`` and a function type ``x -> List EFFECT``.
430+
431+These additional parameters are the list of *input* effects, and a
432+list of *output* effects, computed from the result of an effectful
433+operation. That is: running an effectful program can change the set
434+of effects available! This is a particularly powerful idea, and we
435+will see its consequences in more detail later. Some examples of
436+operations which can change the set of available effects are:
437+
438+- Updating a state containing a dependent type (for example adding an
439+ element to a vector).
440+
441+- Opening a file for reading is an effect, but whether the file really
442+ *is* open afterwards depends on whether the file was successfully
443+ opened.
444+
445+- Closing a file means that reading from the file should no longer be
446+ possible.
447+
448+While powerful, this can make uses of the ``Eff`` type hard to read.
449+Therefore, the library provides syntactic sugar which is translated
450+such that:
451+
452+.. code-block:: idris
453+
454+ { xs } Eff a
455+
456+is expanded to
457+
458+.. code-block:: idris
459+
460+ Eff a xs (\_ => xs)
461+
462+i.e. the set of effects remains the same on output. This suffices for
463+the ``STATE`` example we have seen so far, and for many useful
464+side-effecting programs. We could also have written ``treeTagAux``
465+with the expanded type:
466+
467+.. code-block:: idris
468+
469+ treeTagAux : BTree a ->
470+ Eff (BTree (Int, a)) [STATE Int] (\x => [STATE Int])
471+
472+Later, we will see programs which update effects:
473+
474+.. code-block:: idris
475+
476+ { xs ==> xs' } Eff a
477+
478+which is expanded to
479+
480+.. code-block:: idris
481+
482+ Eff a xs (\_ => xs')
483+
484+i.e. the set of effects is updated to ``xs’`` (think of a transition
485+in a state machine). There is, for example, a version of ``put`` which
486+updates the type of the state:
487+
488+.. code-block:: idris
489+
490+ putM : y -> { [STATE x] ==> [STATE y] } Eff ()
491+
492+Also, we have:
493+
494+.. code-block:: idris
495+
496+ { xs ==> {res} xs' } Eff a
497+
498+which is expanded to
499+
500+.. code-block:: idris
501+
502+ Eff a xs (\res => xs')
503+
504+i.e. the set of effects is updated according to the result of the
505+operation ``res``.
506+
507+.. [1] The earlier paper [3]_ describes the essential implementation
508+ details, although the library presented there is an earlier version
509+ which is less powerful than that presented in this tutorial.
510+
511+.. [2] In practice, ``’name`` simply introduces a new empty type
512+
513+.. [3] Edwin Brady. 2013. Programming and reasoning with algebraic
514+ effects and dependent types. SIGPLAN Not. 48, 9 (September
515+ 2013), 133-144. DOI=10.1145/2544174.2500581
516+ http://doi.acm.org/10.1145/2544174.2500581
517+
518+.. |image| image:: ../image/effects-tree.png
519+ :width: 500px
docs/effects/summary.rstnew file+153
@@ -0,0 +1,153 @@
1+.. _sect-appendix:
2+
3+===============
4+Effects Summary
5+===============
6+
7+This appendix gives interfaces for the core effects provided by the
8+library.
9+
10+EXCEPTION
11+---------
12+
13+.. code-block:: idris
14+
15+ module Effect.Exception
16+
17+ import Effects
18+ import System
19+ import Control.IOExcept
20+
21+ EXCEPTION : Type -> EFFECT
22+
23+ raise : a -> { [EXCEPTION a ] } Eff m b
24+
25+ instance Handler (Exception a) Maybe
26+ instance Handler (Exception a) List
27+ instance Handler (Exception a) (Either a)
28+ instance Handler (Exception a) (IOExcept a)
29+ instance Show a => Handler (Exception a) IO
30+
31+FILE\_IO
32+--------
33+
34+.. code-block:: idris
35+
36+ module Effect.File
37+
38+ import Effects
39+ import Control.IOExcept
40+
41+ FILE_IO : Type -> EFFECT
42+
43+ data OpenFile : Mode -> Type
44+
45+ open : Handler FileIO e => String -> (m : Mode) ->
46+ { [FILE_IO ()] ==>
47+ {ok} [FILE_IO (if ok then OpenFile m else ())] } Eff e Bool
48+ close : Handler FileIO e =>
49+ { [FILE_IO (OpenFile m)] ==> [FILE_IO ()] } Eff e ()
50+
51+ readLine : Handler FileIO e =>
52+ { [FILE_IO (OpenFile Read)] } Eff e String
53+ writeLine : Handler FileIO e => String ->
54+ { [FILE_IO (OpenFile Write)] } Eff e ()
55+ eof : Handler FileIO e =>
56+ { [FILE_IO (OpenFile Read)] } Eff e Bool
57+
58+ instance Handler FileIO IO
59+
60+RND
61+---
62+
63+.. code-block:: idris
64+
65+ module Effect.Random
66+
67+ import Effects
68+ import Data.Vect
69+ import Data.Fin
70+
71+ RND : EFFECT
72+
73+ srand : Integer -> { [RND] } Eff m ()
74+ rndInt : Integer -> Integer -> { [RND] } Eff m Integer
75+ rndFin : (k : Nat) -> { [RND] } Eff m (Fin (S k))
76+
77+ instance Handler Random m
78+
79+SELECT
80+------
81+
82+.. code-block:: idris
83+
84+ module Effect.Select
85+
86+ import Effects
87+
88+ SELECT : EFFECT
89+
90+ select : List a -> { [SELECT] } Eff m a
91+
92+ instance Handler Selection Maybe
93+ instance Handler Selection List
94+
95+STATE
96+-----
97+
98+.. code-block:: idris
99+
100+ module Effect.State
101+
102+ import Effects
103+
104+ STATE : Type -> EFFECT
105+
106+ get : { [STATE x] } Eff m x
107+ put : x -> { [STATE x] } Eff m ()
108+ putM : y -> { [STATE x] ==> [STATE y] } Eff m ()
109+ update : (x -> x) -> { [STATE x] } Eff m ()
110+
111+ instance Handler State m
112+
113+STDIO
114+-----
115+
116+.. code-block:: idris
117+
118+ module Effect.StdIO
119+
120+ import Effects
121+ import Control.IOExcept
122+
123+ STDIO : EFFECT
124+
125+ putChar : Handler StdIO m => Char -> { [STDIO] } Eff m ()
126+ putStr : Handler StdIO m => String -> { [STDIO] } Eff m ()
127+ putStrLn : Handler StdIO m => String -> { [STDIO] } Eff m ()
128+
129+ getStr : Handler StdIO m => { [STDIO] } Eff m String
130+ getChar : Handler StdIO m => { [STDIO] } Eff m Char
131+
132+ instance Handler StdIO IO
133+ instance Handler StdIO (IOExcept a)
134+
135+SYSTEM
136+------
137+
138+.. code-block:: idris
139+
140+ module Effect.System
141+
142+ import Effects
143+ import System
144+ import Control.IOExcept
145+
146+ SYSTEM : EFFECT
147+
148+ getArgs : Handler System e => { [SYSTEM] } Eff e (List String)
149+ time : Handler System e => { [SYSTEM] } Eff e Int
150+ getEnv : Handler System e => String -> { [SYSTEM] } Eff e (Maybe String)
151+
152+ instance Handler System IO
153+ instance Handler System (IOExcept a)
docs/faq/faq.rstnew file+130
@@ -0,0 +1,130 @@
1+==========================
2+Frequently Asked Questions
3+==========================
4+
5+What are the differences between Agda and Idris?
6+------------------------------------------------
7+
8+The main difference is that Idris has been designed from the start to support
9+verified systems programming through easy interoperability with C and high
10+level language constructs to support domain specific language implementation.
11+Idris emphasises general-purpose programming, rather than theorem proving, and
12+as such includes higher level programming constructs such as type classes and
13+do notation. Idris also supports tactic based theorem proving, and has a
14+lightweight Hugs/GHCI style interface.
15+
16+Is Idris production ready?
17+--------------------------
18+
19+Idris is primarily a research tool for exploring the possibilities of software
20+development with dependent types, meaning that the primary goal is not (yet) to
21+make a system which could be used in production. As such, there are a few rough
22+corners, and lots of missing libraries. Nobody is working on Idris full time,
23+and we don't have the resources at the moment to polish the system on our own.
24+Therefore, we don't recommend building your business around it!
25+
26+Having said that, contributions which help towards making Idris suitable
27+for use in production would be very welcome - this includes (but is not
28+limited to) extra library support, polishing the run-time system (and ensuring
29+it is robust), providing and maintaining a JVM back end, etc.
30+
31+Why does Idris use eager evaluation rather than lazy?
32+-----------------------------------------------------
33+
34+Idris uses eager evaluation for more predictable performance, in particular
35+because one of the longer term goals is to be able to write efficient and
36+verified low level code such as device drivers and network infrastructure.
37+Furthermore, the Idris type system allows us to state precisely the type
38+of each value, and therefore the run-time form of each value. In a lazy
39+language, consider a value of type ``Int``:
40+
41+.. code-block:: idris
42+
43+ thing : Int
44+
45+What is the representation of ``thing`` at run-time? Is it a bit pattern
46+representing an integer, or is it a pointer to some code which will compute
47+an integer? In Idris, we have decided that we would like to make this
48+distinction precise, in the type:
49+
50+.. code-block:: idris
51+
52+ thing_val : Int
53+ thing_comp : Lazy Int
54+
55+Here, it is clear from the type that ``thing_val`` is guaranteed to be a
56+concrete ``Int``, whereas ``thing_comp`` is a computation which will produce an
57+``Int``.
58+
59+How can I make lazy control structures?
60+---------------------------------------
61+
62+You can make control structures using the special Lazy type. For example,
63+``if...then...else`` is defined as follows in the library:
64+
65+.. code-block:: idris
66+
67+ boolElim : Bool -> (t : Lazy a) -> (e : Lazy a) -> a
68+ boolElim True t e = t
69+ boolElim False t e = e
70+
71+ syntax if [test] then [t] else [e] = boolElim test t e
72+
73+The type ``Lazy a`` for ``t`` and ``f`` indicates that those arguments will
74+only be evaluated if they are used, that is, they are evaluated lazily.
75+
76+Evaluation at the REPL doesn't behave as I expect. What's going on?
77+-------------------------------------------------------------------
78+
79+Being a fully dependently typed language, Idris has two phases where it
80+evaluates things, compile-time and run-time. At compile-time it will only
81+evaluate things which it knows to be total (i.e. terminating and covering all
82+possible inputs) in order to keep type checking decidable. The compile-time
83+evaluator is part of the Idris kernel, and is implemented in Haskell using a
84+HOAS (higher order abstract syntax) style representation of values. Since
85+everything is known to have a normal form here, the evaluation strategy doesn't
86+actually matter because either way it will get the same answer, and in practice
87+it will do whatever the Haskell run-time system chooses to do.
88+
89+The REPL, for convenience, uses the compile-time notion of evaluation. As well
90+as being easier to implement (because we have the evaluator available) this can
91+be very useful to show how terms evaluate in the type checker. So you can see
92+the difference between:
93+
94+.. code-block:: idris
95+
96+ Idris> \n, m => (S n) + m
97+ \n => \m => S (plus n m) : Nat -> Nat -> Nat
98+
99+ Idris> \n, m => n + (S m)
100+ \n => \m => plus n (S m) : Nat -> Nat -> Nat
101+
102+When will Idris be self-hosting?
103+--------------------------------
104+
105+It’s not a priority, though not a bad idea in the long run. It would be a
106+worthwhile effort in the short term to implement libraries to support
107+self-hosting, such as a good parsing library.
108+
109+Does Idris have Universe Polymorphism? What is the type of ``Type``?
110+--------------------------------------------------------------------
111+
112+Rather than Universe polymorphism, Idris has a cumulative hierarchy of
113+universes; ``Type : Type 1``, ``Type 1 : Type 2``, etc.
114+Cumulativity means that if ``x : Type n`` then also ``x : Type m``,
115+provided that ``n <= m``.
116+
117+What does the name ‘Idris’ mean?
118+--------------------------------
119+
120+British people of a certain age may be familiar with this
121+`singing dragon <https://www.youtube.com/watch?v=G5ZMNyscPcg>`_. If
122+that doesn’t help, maybe you can invent a suitable acronym :-) .
123+
124+Where can I find more answers?
125+------------------------------
126+
127+There is an `Unofficial FAQ
128+<https://github.com/idris-lang/Idris-dev/wiki/Unofficial-FAQ>`_ on the wiki on
129+github which answers more technical questions and may be updated more often.
130+
docs/faq/index.rstnew file+19
@@ -0,0 +1,19 @@
1+.. _faq-index:
2+
3+##########################
4+Frequently Asked Questions
5+##########################
6+
7+.. note::
8+ The documentation for Idris has been published under the Creative
9+ Commons CC0 License. As such to the extent possible under law, *The
10+ Idris Community* has waived all copyright and related or neighboring
11+ rights to Documentation for Idris.
12+
13+ More information concerning the CC0 can be found online at: http://creativecommons.org/publicdomain/zero/1.0/
14+
15+
16+.. toctree::
17+ :maxdepth: 1
18+
19+ faq
docs/guides/index.rstnew file+21
@@ -0,0 +1,21 @@
1+.. _guides-index:
2+
3+################################
4+Tutorials on the Idris Language
5+################################
6+
7+Tutorials submitted by community members.
8+
9+.. note::
10+ The documentation for Idris has been published under the Creative
11+ Commons CC0 License. As such to the extent possible under law, *The
12+ Idris Community* has waived all copyright and related or neighboring
13+ rights to Documentation for Idris.
14+
15+ More information concerning the CC0 can be found online at: http://creativecommons.org/publicdomain/zero/1.0/
16+
17+
18+.. toctree::
19+ :maxdepth: 1
20+
21+ type-providers-ffi
docs/guides/type-providers-ffi.rstnew file+290
@@ -0,0 +1,290 @@
1+Type Providers in Idris
2+=======================
3+
4+`Type providers in Idris
5+<http://www.itu.dk/people/drc/pubs/dependent-type-providers.pdf>`__
6+are simple enough, but there are a few caveats to using them that it
7+would be worthwhile to go through the basic steps. We also go over
8+foreign functions, because these will often be used with type
9+providers.
10+
11+The use case
12+------------
13+
14+First, let's talk about *why* we might want type providers. There are
15+a number of reasons to use them and there are other examples available
16+around the net, but in this tutorial we'll be using them to port C's
17+``struct stat`` to Idris.
18+
19+Why do we need type providers? Well, Idris's FFI needs to know the
20+types of the things it passes to and from C, but the fields of a
21+``struct stat`` are implementation-dependent types that cannot be
22+relied upon. We don't just want to hard-code these types into our
23+program... so we'll use a type provider to find them at compile time!
24+
25+A simple example
26+----------------
27+
28+First, let's go over a basic usage of type providers, because foreign
29+functions can be confusing but it's important to remember that
30+providers themselves are simple.
31+
32+A type provider is simply an IO action that returns a value of this
33+type:
34+
35+.. code-block:: idris
36+
37+ data Provider a = Provide a | Error String
38+
39+Looks familiar? ``Provider`` is just ``Either a String``, given a
40+slightly more descriptive name.
41+
42+Remember though, type providers we use in our program must be IO
43+actions. Let's write a simple one now:
44+
45+.. code-block:: idris
46+
47+ module Provider
48+ -- Asks nicely for the user to supply the size of C's size_t type on this
49+ -- machine
50+ getSizeT : IO (Provider Int)
51+ getSizeT = do
52+ putStrLn "I'm sorry, I don't know how big size_t is. Can you tell me, in bytes?"
53+ resp <- getLine
54+ case readInt resp of
55+ Just sizeTSize => return (Provide sizeTSize)
56+ Nothing => return (Error "I'm sorry, I don't understand.")
57+ -- the readInt function is left as an exercise
58+
59+We assume that whoever's compiling the library knows the size of
60+``size_t``, so we'll just ask them! (Don't worry, we'll get it
61+ourselves later.) Then, if their response can be converted to an
62+integer, we present ``Provide sizeTSize`` as the result of our IO
63+action; or if it can't, we signal a failure. (This will then become a
64+compile-time error.)
65+
66+Now we can use this IO action as a type provider:
67+
68+.. code-block:: idris
69+
70+ module Main
71+ -- to gain access to the IO action we're using as a provider
72+ import Provider
73+
74+ -- TypeProviders is an extension, so we'll enable it
75+ %language TypeProviders
76+
77+ -- And finally, use the provider!
78+ -- Note that the parentheses are mandatory.
79+ %provide (sizeTSize : Int) with getSizeT
80+
81+ -- From now on it's just a normal program where `sizeTSize` is available
82+ -- as a top-level constant
83+ main : IO ()
84+ main = do
85+ putStr "Look! I figured out how big size_t is! It's "
86+ putStr (show sizeTSize)
87+ putStr " bytes!"
88+
89+Yay! We... asked the user something at compile time? That's not very
90+good, actually. Our library is going to be difficult to compile! This
91+is hardly a step up from having them edit in the size of ``size_t``
92+themselves!
93+
94+Don't worry, there's a better way.
95+
96+Foreign Functions
97+-----------------
98+
99+It's actually pretty easy to write a C function that figures out the
100+size of ``size_t``:
101+
102+.. code:: c
103+
104+ int sizeof_size_t() { return sizeof(size_t); }
105+
106+(Why an int and not a ``size_t``? The FFI needs to know how to receive
107+the return value of this function and translate it into an Idris
108+value. If we knew how to do this for values of C type ``size_t``, we
109+wouldn't need to write this function at all! If we really wanted to be
110+safe from overflow, we could use an array of multiple integers, but
111+the SIZE of ``size_t`` is never going to be a 65535 byte integer.)
112+
113+So now we can get the size of ``size_t`` as long as we're in C code.
114+We'd like to be able to use this from Idris. Can we do this? It turns
115+out we can.
116+
117+mkForeign
118+~~~~~~~~~
119+
120+With mkForeign, we can turn a C function into an IO action. It works
121+like this:
122+
123+.. code-block:: idris
124+
125+ getSizeT : IO Int
126+ getSizeT = mkForeign (FFun "sizeof_size_t" [] FInt)
127+
128+Pretty simple. ``mkForeign`` takes a specification of what function it
129+needs to call, and we construct this specification with ``FFun``. And
130+``FFun`` just takes a name, a list of argument types (we have none),
131+and a return type.
132+
133+One thing you might want to note: the return type we've specified is
134+``FInt``, not ``Int``. That's because ``Int`` is an idris type and C
135+functions don't return idris types. ``FInt`` is not an idris type, but
136+is just the representation of the type of a C int. It tells the
137+compiler "Treat the return value of this C function like it's a C int,
138+and when you pass it back into Idris, convert it to an Idris int."
139+
140+Caveats of mkForeign
141+^^^^^^^^^^^^^^^^^^^^
142+
143+First and foremost: ``mkForeign`` is not actually a function. It is
144+treated specially by the compiler, and there are certain rules you
145+need to follow when using it.
146+
147+- Rule 1: the name string must be a literal or constant
148+
149+This does not work:
150+
151+.. code-block:: idris
152+
153+ intIntToInt : String -> Int -> Int -> IO Int
154+ intIntToInt name = mkForeign (FFun name [FInt, FInt] FInt)
155+
156+You'll just have to bite the bullet and write out the whole
157+``mkForeign`` and ``FFun`` expression each time.
158+
159+- Rule 2: the "call" to ``mkForeign`` must be fully applied
160+
161+This just means that every argument appearing in the list of argument
162+types must be applied wherever you write ``mkForeign``. The arguments
163+don't have to be literals or even known at compile time; they just
164+have to be there. For example, if we have ``strlen : String -> IO
165+Int``, then this is fine:
166+
167+.. code-block:: idris
168+
169+ strlen str = mkForeign (FFun "strlen" [FString] FInt) str
170+
171+but this is not fine:
172+
173+.. code-block:: idris
174+
175+ strlen = mkForeign (FFun "strlen" [FString] FInt)
176+
177+Note that this only applies to places where you literally typed
178+``mkForeign``. Once you've defined it, ``strlen`` is just a normal
179+function returning an IO action, and it doesn't need to be fully
180+applied. This is okay:
181+
182+.. code-block:: idris
183+
184+ lengths : IO [Int]
185+ lengths = mapM strlen listOfStrings
186+
187+Running foreign functions
188+~~~~~~~~~~~~~~~~~~~~~~~~~
189+
190+This is all well and good for writing code that will typecheck. To
191+actually run the code, we'll need to do just a bit more work. Exactly
192+what we need to do depends on whether we want to interpret or compile
193+our code.
194+
195+In the interpreter
196+^^^^^^^^^^^^^^^^^^
197+
198+If we want to call our foreign functions from interpreted code (such
199+as the REPL or a type provider), we need to dynamically link a library
200+containing the symbols we need. This is pretty easy to do with the
201+``%dynamic`` directive:
202+
203+.. code-block:: idris
204+
205+ %dynamic "./filename.so"
206+
207+Note that the leading "./" is important: currently, the string you
208+provide is interpreted as by ``dlopen()``, which on Unix does not search
209+in the current directory by default. If you use the "./", the library
210+will be searched for in the directory from which you run idris (*not*
211+the location of the file you're running!). Of course, if you're using
212+functions from an installed library rather than something you wrote
213+yourself, the "./" is not necessary.
214+
215+In an executable
216+^^^^^^^^^^^^^^^^
217+
218+If we want to run our code from an executable, we can statically link
219+instead. We'll use the ``%include`` and ``%link`` directives:
220+
221+.. code-block:: idris
222+
223+ %include C "filename.h"
224+ %link C "filename.o"
225+
226+Note the extra argument to the directive! We specify that we're
227+linking a C header and library. Also, unlike ``%dynamic``, these
228+directives search in the current directory by default. (That is, the
229+directory from which we run idris.)
230+
231+Putting it all together
232+-----------------------
233+
234+So, at the beginning of this article I said we'd use type providers to
235+port ``struct stat`` to Idris. The relevant part is just translating
236+all the mysterious typedef'd C types into Idris types, and that's what
237+we'll do here.
238+
239+First, let's write a C file containing functions that we'll bind to.
240+
241+.. code-block:: c
242+
243+ /* stattypes.c */
244+ int sizeof_dev_t() { return sizeof(dev_t); }
245+ int sizeof_ino_t() { return sizeof(ino_t); }
246+ /* lots more functions like this */
247+
248+Next, an Idris file to define our providers:
249+
250+.. code-block:: idris
251+
252+ -- Providers.idr
253+ module Providers
254+
255+ %dynamic "./stattypes.so"
256+
257+ sizeOfDevT : IO Int
258+ sizeOfDevT = mkForeign (FFun "sizeof_dev_t" [] FInt)
259+ {- lots of similar functions -}
260+
261+ -- now we have an integer, but we want a Provider FTy
262+ -- since our sizeOf* functions are ordinary IO actions, we
263+ -- can just map over them.
264+ bytesToType : Int -> Provider FTy
265+ bytesToType 1 = Provide (FIntT IT8) -- "8 bit foreign integer"
266+ bytesToType 2 = Provide (FIntT IT16)
267+ bytesToType 4 = Provide (FIntT IT32)
268+ bytesToType 8 = Provide (FIntT IT64)
269+ bytesToType _ = Error "Unrecognized integral type."
270+
271+ getDevT : IO (Provider FTy)
272+ getDevT = map bytesToType sizeOfDevT
273+ {- lots of similar functions -}
274+
275+Finally, we'll write one more idris file where we use the type
276+providers:
277+
278+.. code-block:: idris
279+
280+ -- Main.idr
281+ module Main
282+ import Providers
283+ %language TypeProviders
284+ %provide (FDevT : FTy) with getDevT
285+
286+ -- interpFTy translates a foreign type to the corresponding idris type
287+ DevT : Type
288+ DevT = interpFTy FDevT -- on most systems, DevT = Bits64
289+
290+ -- We can now use DevT in our program and FDevT in our FFun expressions!
docs/image/effects-tree.pngnew file

Binary file not shown.

docs/index.rstnew file+115
@@ -0,0 +1,115 @@
1+.. Idris Manual documentation master file, created by
2+ sphinx-quickstart on Sat Feb 28 20:41:47 2015.
3+ You can adapt this file completely to your liking, but it should at least
4+ contain the root `toctree` directive.
5+
6+Documentation for the Idris Language
7+====================================
8+
9+.. note::
10+
11+ The documentation for Idris has been published under the Creative
12+ Commons CC0 License. As such to the extent possible under law, *The
13+ Idris Community* has waived all copyright and related or neighboring
14+ rights to Documentation for Idris.
15+
16+ More information concerning the CC0 can be found online at: http://creativecommons.org/publicdomain/zero/1.0/
17+
18+* :ref:`tutorial-index`
19+* :ref:`eff-tutorial-index`
20+* :ref:`faq-index`
21+* :ref:`proofs-index`
22+* :ref:`reference-index`
23+* :ref:`guides-index`
24+
25+
26+.. _tutorial:
27+
28+###################
29+The Idris Tutorial
30+###################
31+
32+.. toctree::
33+ :maxdepth: 1
34+
35+ tutorial/introduction
36+ tutorial/starting
37+ tutorial/typesfuns
38+ tutorial/classes
39+ tutorial/modules
40+ tutorial/packages
41+ tutorial/interp
42+ tutorial/views
43+ tutorial/theorems
44+ tutorial/provisional
45+ tutorial/interactive
46+ tutorial/syntax
47+ tutorial/miscellany
48+ tutorial/conclusions
49+
50+.. _effects:
51+
52+##########################
53+Frequently Asked Questions
54+##########################
55+
56+.. toctree::
57+ :maxdepth: 1
58+
59+ faq/faq
60+
61+.. _effects:
62+
63+################
64+Learning Effects
65+################
66+
67+.. toctree::
68+ :maxdepth: 1
69+
70+ effects/introduction
71+ effects/state
72+ effects/simpleeff
73+ effects/depeff
74+ effects/impleff
75+ effects/hangman
76+ effects/conclusions
77+ effects/summary
78+
79+.. _proofs:
80+
81+###############
82+Theorem Proving
83+###############
84+
85+.. toctree::
86+ :maxdepth: 1
87+
88+ proofs/pluscomm
89+ proofs/inductive
90+ proofs/patterns
91+
92+.. _reference:
93+
94+##################
95+Language Reference
96+##################
97+
98+.. toctree::
99+ :maxdepth: 1
100+
101+ reference/documenting
102+ reference/uniqueness-types
103+ reference/ffi
104+ reference/erasure
105+
106+.. _guides:
107+
108+############
109+Short Guides
110+############
111+
112+.. toctree::
113+ :maxdepth: 1
114+
115+ guides/type-providers-ffi
docs/listing/idris-prompt-helloworld.txtnew file+15
@@ -0,0 +1,15 @@
1+$ idris hello.idr
2+ ____ __ _
3+ / _/___/ /____(_)____
4+ / // __ / ___/ / ___/ Version 0.9.17
5+ _/ // /_/ / / / (__ ) http://www.idris-lang.org/
6+ /___/\__,_/_/ /_/____/ Type :? for help
7+
8+Type checking ./hello.idr
9+*hello> :t main
10+Main.main : IO ()
11+*hello> :c hello
12+*hello> :q
13+Bye bye
14+$ ./hello
15+Hello world
docs/listing/idris-prompt-interp.txtnew file+12
@@ -0,0 +1,12 @@
1+$ idris interp.idr
2+ ____ __ _
3+ / _/___/ /____(_)____
4+ / // __ / ___/ / ___/ Version 0.9.17
5+ _/ // /_/ / / / (__ ) http://www.idris-lang.org/
6+ /___/\__,_/_/ /_/____/ Type :? for help
7+
8+Type checking ./interp.idr
9+*interp> :exec
10+Enter a number: 6
11+720
12+*interp>
docs/listing/idris-prompt-start.txtnew file+8
@@ -0,0 +1,8 @@
1+$ idris
2+ ____ __ _
3+ / _/___/ /____(_)____
4+ / // __ / ___/ / ___/ Version 0.9.17
5+ _/ // /_/ / / / (__ ) http://www.idris-lang.org/
6+/___/\__,_/_/ /_/____/ Type :? for help
7+
8+Idris>
docs/make.batnew file+263
@@ -0,0 +1,263 @@
1+@ECHO OFF
2+
3+REM Command file for Sphinx documentation
4+
5+if "%SPHINXBUILD%" == "" (
6+ set SPHINXBUILD=sphinx-build
7+)
8+set BUILDDIR=_build
9+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
10+set I18NSPHINXOPTS=%SPHINXOPTS% .
11+if NOT "%PAPER%" == "" (
12+ set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
13+ set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
14+)
15+
16+if "%1" == "" goto help
17+
18+if "%1" == "help" (
19+ :help
20+ echo.Please use `make ^<target^>` where ^<target^> is one of
21+ echo. html to make standalone HTML files
22+ echo. dirhtml to make HTML files named index.html in directories
23+ echo. singlehtml to make a single large HTML file
24+ echo. pickle to make pickle files
25+ echo. json to make JSON files
26+ echo. htmlhelp to make HTML files and a HTML help project
27+ echo. qthelp to make HTML files and a qthelp project
28+ echo. devhelp to make HTML files and a Devhelp project
29+ echo. epub to make an epub
30+ echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
31+ echo. text to make text files
32+ echo. man to make manual pages
33+ echo. texinfo to make Texinfo files
34+ echo. gettext to make PO message catalogs
35+ echo. changes to make an overview over all changed/added/deprecated items
36+ echo. xml to make Docutils-native XML files
37+ echo. pseudoxml to make pseudoxml-XML files for display purposes
38+ echo. linkcheck to check all external links for integrity
39+ echo. doctest to run all doctests embedded in the documentation if enabled
40+ echo. coverage to run coverage check of the documentation if enabled
41+ goto end
42+)
43+
44+if "%1" == "clean" (
45+ for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
46+ del /q /s %BUILDDIR%\*
47+ goto end
48+)
49+
50+
51+REM Check if sphinx-build is available and fallback to Python version if any
52+%SPHINXBUILD% 2> nul
53+if errorlevel 9009 goto sphinx_python
54+goto sphinx_ok
55+
56+:sphinx_python
57+
58+set SPHINXBUILD=python -m sphinx.__init__
59+%SPHINXBUILD% 2> nul
60+if errorlevel 9009 (
61+ echo.
62+ echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
63+ echo.installed, then set the SPHINXBUILD environment variable to point
64+ echo.to the full path of the 'sphinx-build' executable. Alternatively you
65+ echo.may add the Sphinx directory to PATH.
66+ echo.
67+ echo.If you don't have Sphinx installed, grab it from
68+ echo.http://sphinx-doc.org/
69+ exit /b 1
70+)
71+
72+:sphinx_ok
73+
74+
75+if "%1" == "html" (
76+ %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
77+ if errorlevel 1 exit /b 1
78+ echo.
79+ echo.Build finished. The HTML pages are in %BUILDDIR%/html.
80+ goto end
81+)
82+
83+if "%1" == "dirhtml" (
84+ %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
85+ if errorlevel 1 exit /b 1
86+ echo.
87+ echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
88+ goto end
89+)
90+
91+if "%1" == "singlehtml" (
92+ %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
93+ if errorlevel 1 exit /b 1
94+ echo.
95+ echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
96+ goto end
97+)
98+
99+if "%1" == "pickle" (
100+ %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
101+ if errorlevel 1 exit /b 1
102+ echo.
103+ echo.Build finished; now you can process the pickle files.
104+ goto end
105+)
106+
107+if "%1" == "json" (
108+ %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
109+ if errorlevel 1 exit /b 1
110+ echo.
111+ echo.Build finished; now you can process the JSON files.
112+ goto end
113+)
114+
115+if "%1" == "htmlhelp" (
116+ %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
117+ if errorlevel 1 exit /b 1
118+ echo.
119+ echo.Build finished; now you can run HTML Help Workshop with the ^
120+.hhp project file in %BUILDDIR%/htmlhelp.
121+ goto end
122+)
123+
124+if "%1" == "qthelp" (
125+ %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
126+ if errorlevel 1 exit /b 1
127+ echo.
128+ echo.Build finished; now you can run "qcollectiongenerator" with the ^
129+.qhcp project file in %BUILDDIR%/qthelp, like this:
130+ echo.^> qcollectiongenerator %BUILDDIR%\qthelp\IdrisManual.qhcp
131+ echo.To view the help file:
132+ echo.^> assistant -collectionFile %BUILDDIR%\qthelp\IdrisManual.ghc
133+ goto end
134+)
135+
136+if "%1" == "devhelp" (
137+ %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
138+ if errorlevel 1 exit /b 1
139+ echo.
140+ echo.Build finished.
141+ goto end
142+)
143+
144+if "%1" == "epub" (
145+ %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
146+ if errorlevel 1 exit /b 1
147+ echo.
148+ echo.Build finished. The epub file is in %BUILDDIR%/epub.
149+ goto end
150+)
151+
152+if "%1" == "latex" (
153+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
154+ if errorlevel 1 exit /b 1
155+ echo.
156+ echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
157+ goto end
158+)
159+
160+if "%1" == "latexpdf" (
161+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
162+ cd %BUILDDIR%/latex
163+ make all-pdf
164+ cd %~dp0
165+ echo.
166+ echo.Build finished; the PDF files are in %BUILDDIR%/latex.
167+ goto end
168+)
169+
170+if "%1" == "latexpdfja" (
171+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
172+ cd %BUILDDIR%/latex
173+ make all-pdf-ja
174+ cd %~dp0
175+ echo.
176+ echo.Build finished; the PDF files are in %BUILDDIR%/latex.
177+ goto end
178+)
179+
180+if "%1" == "text" (
181+ %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
182+ if errorlevel 1 exit /b 1
183+ echo.
184+ echo.Build finished. The text files are in %BUILDDIR%/text.
185+ goto end
186+)
187+
188+if "%1" == "man" (
189+ %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
190+ if errorlevel 1 exit /b 1
191+ echo.
192+ echo.Build finished. The manual pages are in %BUILDDIR%/man.
193+ goto end
194+)
195+
196+if "%1" == "texinfo" (
197+ %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
198+ if errorlevel 1 exit /b 1
199+ echo.
200+ echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
201+ goto end
202+)
203+
204+if "%1" == "gettext" (
205+ %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
206+ if errorlevel 1 exit /b 1
207+ echo.
208+ echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
209+ goto end
210+)
211+
212+if "%1" == "changes" (
213+ %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
214+ if errorlevel 1 exit /b 1
215+ echo.
216+ echo.The overview file is in %BUILDDIR%/changes.
217+ goto end
218+)
219+
220+if "%1" == "linkcheck" (
221+ %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
222+ if errorlevel 1 exit /b 1
223+ echo.
224+ echo.Link check complete; look for any errors in the above output ^
225+or in %BUILDDIR%/linkcheck/output.txt.
226+ goto end
227+)
228+
229+if "%1" == "doctest" (
230+ %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
231+ if errorlevel 1 exit /b 1
232+ echo.
233+ echo.Testing of doctests in the sources finished, look at the ^
234+results in %BUILDDIR%/doctest/output.txt.
235+ goto end
236+)
237+
238+if "%1" == "coverage" (
239+ %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage
240+ if errorlevel 1 exit /b 1
241+ echo.
242+ echo.Testing of coverage in the sources finished, look at the ^
243+results in %BUILDDIR%/coverage/python.txt.
244+ goto end
245+)
246+
247+if "%1" == "xml" (
248+ %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
249+ if errorlevel 1 exit /b 1
250+ echo.
251+ echo.Build finished. The XML files are in %BUILDDIR%/xml.
252+ goto end
253+)
254+
255+if "%1" == "pseudoxml" (
256+ %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
257+ if errorlevel 1 exit /b 1
258+ echo.
259+ echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
260+ goto end
261+)
262+
263+:end
docs/proofs/index.rstnew file+24
@@ -0,0 +1,24 @@
1+.. _proofs-index:
2+
3+###############
4+Theorem Proving
5+###############
6+
7+A tutorial on theorem proving in Idris.
8+
9+.. note::
10+
11+ The documentation for Idris has been published under the Creative
12+ Commons CC0 License. As such to the extent possible under law, *The
13+ Idris Community* has waived all copyright and related or neighboring
14+ rights to Documentation for Idris.
15+
16+ More information concerning the CC0 can be found online at: http://creativecommons.org/publicdomain/zero/1.0/
17+
18+.. toctree::
19+ :maxdepth: 1
20+
21+ pluscomm
22+ inductive
23+ patterns
24+
docs/proofs/inductive.rstnew file+98
@@ -0,0 +1,98 @@
1+Inductive Proofs
2+================
3+
4+Before embarking on proving ``plus_commutes`` in Idris itself, let us
5+consider the overall structure of a proof of some property of natural
6+numbers. Recall that they are defined recursively, as follows:
7+
8+.. code-block:: idris
9+
10+ data Nat : Type where
11+ Z : Nat
12+ S : Nat -> Nat
13+
14+A *total* function over natural numbers must both terminate, and cover
15+all possible inputs. Idris checks functions for totality by cheking that
16+all inputs are covered, and that all recursive calls are on
17+*structurally smaller* values (so recursion will always reach a base
18+case). Recalling ``plus``:
19+
20+.. code-block:: idris
21+
22+ plus : Nat -> Nat -> Nat
23+ plus Z m = m
24+ plus (S k) m = S (plus k m)
25+
26+This is total because it covers all possible inputs (the first argument
27+can only be ``Z`` or ``S k`` for some ``k``, and the second argument
28+``m`` covers all possible ``Nat``\ s) and in the recursive call, ``k``
29+is structurally smaller than ``S k`` so the first argument will always
30+reach the base case ``Z`` in any sequence of recursive calls.
31+
32+In some sense, this resembles a mathematical proof by induction (and
33+this is no coincidence!). For some property ``P`` of a natural number
34+``x``, we can show that ``P`` holds for all ``x`` if:
35+
36+- ``P`` holds for zero (the base case).
37+
38+- Assuming that ``P`` holds for ``k``, we can show ``P`` also holds for
39+ ``S k`` (the inductive step).
40+
41+In ``plus``, the property we are trying to show is somewhat trivial (for
42+all natural numbers ``x``, there is a ``Nat`` which need not have any
43+relation to ``x``). However, it still takes the form of a base case and
44+an inductive step. In the base case, we show that there is a ``Nat``
45+arising from ``plus n m`` when ``n = Z``, and in the inductive step we
46+show that there is a ``Nat`` arising when ``n = S k`` and we know we can
47+get a ``Nat`` inductively from ``plus k m``. We could even write a
48+function capturing all such inductive definitions:
49+
50+.. code-block:: idris
51+
52+ nat_induction : (P : Nat -> Type) -> -- Property to show
53+ (P Z) -> -- Base case
54+ ((k : Nat) -> P k -> P (S k)) -> -- Inductive step
55+ (x : Nat) -> -- Show for all x
56+ P x
57+ nat_induction P p_Z p_S Z = p_Z
58+ nat_induction P p_Z p_S (S k) = p_S k (nat_induction P p_Z p_S k)
59+
60+Using ``nat_induction``, we can implement an equivalent inductive
61+version of ``plus``:
62+
63+.. code-block:: idris
64+
65+ plus_ind : Nat -> Nat -> Nat
66+ plus_ind n m
67+ = nat_induction (\x => Nat)
68+ m -- Base case, plus_ind Z m
69+ (\k, k_rec => S k_rec) -- Inductive step plus_ind (S k) m
70+ -- where k_rec = plus_ind k m
71+ n
72+
73+To prove that ``plus n m = plus m n`` for all natural numbers ``n`` and
74+``m``, we can also use induction. Either we can fix ``m`` and perform
75+induction on ``n``, or vice versa. We can sketch an outline of a proof;
76+performing induction on ``n``, we have:
77+
78+- Property ``P`` is ``\x => plus x m = plus m x``.
79+
80+- Show that ``P`` holds in the base case and inductive step:
81+
82+ - | Base case: ``P Z``, i.e.
83+ | ``plus Z m = plus m Z``, which reduces to
84+ | ``m = plus m Z`` due to the definition of ``plus``.
85+
86+ - | Inductive step: Inductively, we know that ``P k`` holds for a specific, fixed ``k``, i.e.
87+ | ``plus k m = plus m k`` (the induction hypothesis). Given this, show ``P (S k)``, i.e.
88+ | ``plus (S k) m = plus m (S k)``, which reduces to
89+ | ``S (plus k m) = plus m (S k)``. From the induction hypothesis, we can rewrite this to
90+ | ``S (plus m k) = plus m (S k)``.
91+
92+To complete the proof we therefore need to show that ``m = plus m Z``
93+for all natural numbers ``m``, and that ``S (plus m k) = plus m (S k)``
94+for all natural numbers ``m`` and ``k``. Each of these can also be
95+proved by induction, this time on ``m``.
96+
97+We are now ready to embark on a proof of commutativity of ``plus``
98+formally in Idris.
docs/proofs/patterns.rstnew file+350
@@ -0,0 +1,350 @@
1+Pattern Matching Proofs
2+=======================
3+
4+In this section, we will provide a proof of ``plus_commutes`` directly,
5+by writing a pattern matching definition. We will use interactive
6+editing features extensively, since it is significantly easier to
7+produce a proof when the machine can give the types of intermediate
8+values and construct components of the proof itself. The commands we
9+will use are summarised below. Where we refer to commands
10+directly, we will use the Vim version, but these commands have a direct
11+mapping to Emacs commands.
12+
13++---------------------+-----------------+---------------+--------------------------------------------------------------------------------------------+
14+|Command | Vim binding | Emacs binding | Explanation |
15++---------------------+-----------------+---------------+--------------------------------------------------------------------------------------------+
16+| Check type | ``\t`` | ``C-c C-t`` | Show type of identifier or metavariable under the cursor. |
17++---------------------+-----------------+---------------+--------------------------------------------------------------------------------------------+
18+| Proof search | ``\o`` | ``C-c C-a`` | Attempt to solve metavariable under the cursor by applying simple proof search. |
19++---------------------+-----------------+---------------+--------------------------------------------------------------------------------------------+
20+| Make new definition | ``\d`` | ``C-c C-s`` | Add a template definition for the type defined under the cursor. |
21++---------------------+-----------------+---------------+--------------------------------------------------------------------------------------------+
22+| Make lemma | ``\l`` | ``C-c C-e`` | Add a top level function with a type which solves the metavariable under the cursor. |
23++---------------------+-----------------+---------------+--------------------------------------------------------------------------------------------+
24+| Split cases | ``\c`` | ``C-c C-c`` | Create new constructor patterns for each possible case of the variable under the cursor. |
25++---------------------+-----------------+---------------+--------------------------------------------------------------------------------------------+
26+
27+
28+Creating a Definition
29+---------------------
30+
31+To begin, create a file ``pluscomm.idr`` containing the following type
32+declaration:
33+
34+.. code-block:: idris
35+
36+ plus_commutes : (n : Nat) -> (m : Nat) -> n + m = m + n
37+
38+To create a template definition for the proof, press ``\d`` (or the
39+equivalent in your editor of choice) on the line with the type
40+declaration. You should see:
41+
42+.. code-block:: idris
43+
44+ plus_commutes : (n : Nat) -> (m : Nat) -> n + m = m + n
45+ plus_commutes n m = ?plus_commutes_rhs
46+
47+To prove this by induction on ``n``, as we sketched in Section
48+[sect:induction], we begin with a case split on ``n`` (press
49+``\c`` with the cursor over the ``n`` in the definition.) You
50+should see:
51+
52+.. code-block:: idris
53+
54+ plus_commutes : (n : Nat) -> (m : Nat) -> n + m = m + n
55+ plus_commutes Z m = ?plus_commutes_rhs_1
56+ plus_commutes (S k) m = ?plus_commutes_rhs_2
57+
58+If we inspect the types of the newly created metavariables,
59+``plus_commutes_rhs_1`` and ``plus_commutes_rhs_2``, we see that the
60+type of each reflects that ``n`` has been refined to ``Z`` and ``S k``
61+in each respective case. Pressing ``\t`` over
62+``plus_commutes_rhs_1`` shows:
63+
64+.. code-block:: idris
65+
66+ m : Nat
67+ --------------------------------------
68+ plus_commutes_rhs_1 : m = plus m 0
69+
70+Note that ``Z`` renders as ``0`` because the pretty printer renders
71+natural numbers as integer literals for readability. Similarly, for
72+``plus_commutes_rhs_2``:
73+
74+.. code-block:: idris
75+
76+ k : Nat
77+ m : Nat
78+ --------------------------------------
79+ plus_commutes_rhs_2 : S (plus k m) = plus m (S k)
80+
81+It is a good idea to give these slightly more meaningful names:
82+
83+.. code-block:: idris
84+
85+ plus_commutes : (n : Nat) -> (m : Nat) -> n + m = m + n
86+ plus_commutes Z m = ?plus_commutes_Z
87+ plus_commutes (S k) m = ?plus_commutes_S
88+
89+Base Case
90+---------
91+
92+We can create a separate lemma for the base case interactively, by
93+pressing ``\l`` with the cursor over ``plus_commutes_Z``. This
94+yields:
95+
96+.. code-block:: idris
97+
98+ plus_commutes_Z : m = plus m 0
99+
100+ plus_commutes : (n : Nat) -> (m : Nat) -> n + m = m + n
101+ plus_commutes Z m = plus_commutes_Z
102+ plus_commutes (S k) m = ?plus_commutes_S
103+
104+That is, the metavariable has been filled with a call to a top level
105+function ``plus_commutes_Z``. The argument ``m`` has been made implicit
106+because it can be inferred from context when it is applied.
107+
108+Unfortunately, we cannot prove this lemma directly, since ``plus`` is
109+defined by matching on its *first* argument, and here ``plus m 0`` has a
110+specific value for its *second argument* (in fact, the left hand side of
111+the equality has been reduced from ``plus 0 m``.) Again, we can prove
112+this by induction, this time on ``m``.
113+
114+First, create a template definition with ``\d``:
115+
116+.. code-block:: idris
117+
118+ plus_commutes_Z : m = plus m 0
119+ plus_commutes_Z = ?plus_commutes_Z_rhs
120+
121+Since we are going to write this by induction on ``m``, which is
122+implciit, we will need to bring ``m`` into scope manually:
123+
124+.. code-block:: idris
125+
126+ plus_commutes_Z : m = plus m 0
127+ plus_commutes_Z {m} = ?plus_commutes_Z_rhs
128+
129+Now, case split on ``m`` with ``\c``:
130+
131+.. code-block:: idris
132+
133+ plus_commutes_Z : m = plus m 0
134+ plus_commutes_Z {m = Z} = ?plus_commutes_Z_rhs_1
135+ plus_commutes_Z {m = (S k)} = ?plus_commutes_Z_rhs_2
136+
137+Checking the type of ``plus_commutes_Z_rhs_1`` shows the following,
138+which is easily proved by reflection:
139+
140+.. code-block:: idris
141+
142+ --------------------------------------
143+ plus_commutes_Z_rhs_1 : 0 = 0
144+
145+For such trivial proofs, we can let write the proof automatically by
146+pressing ``\o`` with the cursor over ``plus_commutes_Z_rhs_1``.
147+This yields:
148+
149+.. code-block:: idris
150+
151+ plus_commutes_Z : m = plus m 0
152+ plus_commutes_Z {m = Z} = Refl
153+ plus_commutes_Z {m = (S k)} = ?plus_commutes_Z_rhs_2
154+
155+For ``plus_commutes_Z_rhs_2``, we are not so lucky:
156+
157+.. code-block:: idris
158+
159+ k : Nat
160+ --------------------------------------
161+ plus_commutes_Z_rhs_2 : S k = S (plus k 0)
162+
163+Inductively, we should know that ``k = plus k 0``, and we can get access
164+to this inductive hypothesis by making a recursive call on k, as
165+follows:
166+
167+.. code-block:: idris
168+
169+ plus_commutes_Z : m = plus m 0
170+ plus_commutes_Z {m = Z} = Refl
171+ plus_commutes_Z {m = (S k)} = let rec = plus_commutes_Z {m=k} in
172+ ?plus_commutes_Z_rhs_2
173+
174+For ``plus_commutes_Z_rhs_2``, we now see:
175+
176+.. code-block:: idris
177+
178+ k : Nat
179+ rec : k = plus k (fromInteger 0)
180+ --------------------------------------
181+ plus_commutes_Z_rhs_2 : S k = S (plus k 0)
182+
183+Again, the ``fromInteger 0`` is merely due to ``Nat`` being an instance
184+of the ``Num`` typeclass. So we know that ``k = plus k 0``, but how do
185+we use this to update the goal to ``S k = S k``?
186+
187+To achieve this, Idris provides a ``replace`` function as part of the
188+prelude:
189+
190+.. code-block:: idris
191+
192+ *pluscomm> :t replace
193+ replace : (x = y) -> P x -> P y
194+
195+Given a proof that ``x = y``, and a property ``P`` which holds for
196+``x``, we can get a proof of the same property for ``y``, because we
197+know ``x`` and ``y`` must be the same. In practice, this function can be
198+a little tricky to use because in general the implicit argument ``P``
199+can be hard to infer by unification, so Idris provides a high level
200+syntax which calculates the property and applies ``replace``:
201+
202+.. code-block:: idris
203+
204+ rewrite prf in expr
205+
206+If we have ``prf : x = y``, and the required type for ``expr`` is some
207+property of ``x``, the ``rewrite ... in`` syntax will search for ``x``
208+in the required type of ``expr`` and replace it with ``y``. Concretely,
209+in our example, we can say:
210+
211+.. code-block:: idris
212+
213+ plus_commutes_Z {m = (S k)} = let rec = plus_commutes_Z {m=k} in
214+ rewrite rec in ?plus_commutes_Z_rhs_2
215+
216+Checking the type of ``plus_commutes_Z_rhs_2`` now gives:
217+
218+.. code-block:: idris
219+
220+ k : Nat
221+ rec : k = plus k (fromInteger 0)
222+ _rewrite_rule : plus k 0 = k
223+ --------------------------------------
224+ plus_commutes_Z_rhs_2 : S (plus k 0) = S (plus k 0)
225+
226+Using the rewrite rule ``rec`` (which we can see in the context here as
227+``_rewrite_rule``\ [1]_, the goal type has been updated with ``k``
228+replaced by ``plus k 0``.
229+
230+Alternatively, we could have applied the rewrite in the other direction
231+using the ``sym`` function:
232+
233+.. code-block:: idris
234+
235+ *pluscomm> :t sym
236+ sym : (l = r) -> r = l
237+
238+.. code-block:: idris
239+
240+ plus_commutes_Z {m = (S k)} = let rec = plus_commutes_Z {m=k} in
241+ rewrite sym rec in ?plus_commutes_Z_rhs_2
242+
243+In this case, inspecting the type of the hole gives:
244+
245+.. code-block:: idris
246+
247+ k : Nat
248+ rec : k = plus k (fromInteger 0)
249+ _rewrite_rule : k = plus k 0
250+ --------------------------------------
251+ plus_commutes_Z_rhs_2 : S k = S k
252+
253+Either way, we can use proof search (``\o``) to complete the
254+proof, giving:
255+
256+.. code-block:: idris
257+
258+ plus_commutes_Z : m = plus m 0
259+ plus_commutes_Z {m = Z} = Refl
260+ plus_commutes_Z {m = (S k)} = let rec = plus_commutes_Z {m=k} in
261+ rewrite rec in Refl
262+
263+The base case is now complete.
264+
265+Inductive Step
266+--------------
267+
268+Our main theorem, ``plus_commutes`` should currently be in the following
269+state:
270+
271+.. code-block:: idris
272+
273+ plus_commutes : (n : Nat) -> (m : Nat) -> n + m = m + n
274+ plus_commutes Z m = plus_commutes_Z
275+ plus_commutes (S k) m = ?plus_commutes_S
276+
277+Looking again at the type of ``plus_commutes_S``, we have:
278+
279+.. code-block:: idris
280+
281+ k : Nat
282+ m : Nat
283+ --------------------------------------
284+ plus_commutes_S : S (plus k m) = plus m (S k)
285+
286+Conveniently, by induction we can immediately tell that
287+``plus k m = plus m k``, so let us rewrite directly by making a
288+recursive call to ``plus_commutes``. We add this directly, by hand, as
289+follows:
290+
291+.. code-block:: idris
292+
293+ plus_commutes : (n : Nat) -> (m : Nat) -> n + m = m + n
294+ plus_commutes Z m = plus_commutes_Z
295+ plus_commutes (S k) m = rewrite plus_commutes k m in ?plus_commutes_S
296+
297+Checking the type of ``plus_commutes_S`` now gives:
298+
299+.. code-block:: idris
300+
301+ k : Nat
302+ m : Nat
303+ _rewrite_rule : plus m k = plus k m
304+ --------------------------------------
305+ plus_commutes_S : S (plus m k) = plus m (S k)
306+
307+The good news is that ``m`` and ``k`` now appear in the correct order.
308+However, we still have to show that the successor symbol ``S`` can be
309+moved to the front in the right hand side of this equality. This
310+remaining lemma takes a similar form to the ``plus_commutes_Z``; we
311+begin by making a new top level lemma with ``\l``. This gives:
312+
313+.. code-block:: idris
314+
315+ plus_commutes_S : (k : Nat) -> (m : Nat) -> S (plus m k) = plus m (S k)
316+
317+Unlike the previous case, ``k`` and ``m`` are not made implicit because
318+we cannot in general infer arguments to a function from its result.
319+Again, we make a template definition with ``\d``:
320+
321+.. code-block:: idris
322+
323+ plus_commutes_S : (k : Nat) -> (m : Nat) -> S (plus m k) = plus m (S k)
324+ plus_commutes_S k m = ?plus_commutes_S_rhs
325+
326+Again, this is defined by induction over ``m``, since ``plus`` is
327+defined by matching on its first argument. The complete definition is:
328+
329+.. code-block:: idris
330+
331+ total
332+ plus_commutes_S : (k : Nat) -> (m : Nat) -> S (plus m k) = plus m (S k)
333+ plus_commutes_S k Z = Refl
334+ plus_commutes_S k (S j) = rewrite plus_commutes_S k j in Refl
335+
336+All metavariables have now been solved,
337+
338+The ``total`` annotation means that we require the final function to
339+pass the totality checker; i.e. it will terminate on all possible
340+well-typed inputs. This is important for proofs, since it provides a
341+guarantee that the proof is valid in *all* cases, not just those for
342+which it happens to be well-defined.
343+
344+Now that ``plus_commutes`` has a ``total`` annotation, we have completed the
345+proof of commutativity of addition on natural numbers.
346+
347+.. [1]
348+ Note that the left and right hand sides of the equality have been
349+ swapped, because ``replace`` takes a proof of ``x=y`` and the
350+ property for ``x``, not ``y``.
docs/proofs/pluscomm.rstnew file+188
@@ -0,0 +1,188 @@
1+Running example: Addition of Natural Numbers
2+============================================
3+
4+Throughout this tutorial, we will be working with the following
5+function, defined in the Idris prelude, which defines addition on
6+natural numbers:
7+
8+.. code-block:: idris
9+
10+ plus : Nat -> Nat -> Nat
11+ plus Z m = m
12+ plus (S k) m = S (plus k m)
13+
14+It is defined by the above equations, meaning that we have for free the
15+properties that adding ``m`` to zero always results in ``m``, and that
16+adding ``m`` to any non-zero number ``S k`` always results in
17+``S (plus k m)``. We can see this by evaluation at the Idris REPL (i.e.
18+the prompt, the read-eval-print loop):
19+
20+.. code-block:: idris
21+
22+ Idris> \m => plus Z m
23+ \m => m : Nat -> Nat
24+
25+ Idris> \k,m => plus (S k) m
26+ \k => \m => S (plus k m) : Nat -> Nat -> Nat
27+
28+Note that unlike many other language REPLs, the Idris REPL performs
29+evaluation on *open* terms, meaning that it can reduce terms which
30+appear inside lambda bindings, like those above. Therefore, we can
31+introduce unknowns ``k`` and ``m`` as lambda bindings and see how
32+``plus`` reduces.
33+
34+The ``plus`` function has a number of other useful properties, for
35+example:
36+
37+- It is *commutative*, that is for all ``Nat`` inputs ``n`` and ``m``,
38+ we know that ``plus n m = plus m n``.
39+
40+- It is *associative*, that is for all ``Nat`` inputs ``n``, ``m`` and
41+ ``p``, we know that ``plus n (plus m p) = plus (plus m n) p``.
42+
43+We can use these properties in an Idris program, but in order to do so
44+we must *prove* them.
45+
46+Equality Proofs
47+---------------
48+
49+Idris has a built-in propositional equality type, conceptually defined
50+as follows:
51+
52+.. code-block:: idris
53+
54+ data (=) : a -> b -> Type where
55+ Refl : x = x
56+
57+Note that this must be built-in, rather than defined in the library,
58+because ``=`` is a reserved operator — you cannot define this directly
59+in your own code.
60+
61+It is *propositional* equality, where the type states that any two
62+values in different types ``a`` and ``b`` may be proposed to be equal.
63+There is only one way to *prove* equality, however, which is by
64+reflexivity (``Refl``).
65+
66+We have a *type* for propositional equality here, and correspondingly a
67+*program* inhabiting an instance of this type can be seen as a proof of
68+the corresponding proposition [1]_. So, trivially, we can prove that
69+``4`` equals ``4``:
70+
71+.. code-block:: idris
72+
73+ four_eq : 4 = 4
74+ four_eq = Refl
75+
76+However, trying to prove that ``4 = 5`` results in failure:
77+
78+.. code-block:: idris
79+
80+ four_eq_five : 4 = 5
81+ four_eq_five = Refl
82+
83+The type ``4 = 5`` is a perfectly valid type, but is uninhabited, so
84+when trying to type check this definition, Idris gives the following
85+error:
86+
87+::
88+
89+ When elaborating right hand side of four_eq_five:
90+ Can't unify
91+ x = x (Type of Refl)
92+ with
93+ 4 = 5 (Expected type)
94+
95+Type checking equality proofs
96+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
97+
98+An important step in type checking Idris programs is *unification*,
99+which attempts to resolve implicit arguments such as the implicit
100+argument ``x`` in ``Refl``. As far as our understanding of type checking
101+proofs is concerned, it suffices to know that unifying two terms
102+involves reducing both to normal form then trying to find an assignment
103+to implicit arguments which will make those normal forms equal.
104+
105+When type checking ``Refl``, Idris requires that the type is of the form
106+``x = x``, as we see from the type of ``Refl``. In the case of
107+``four_eq_five``, Idris will try to unify the expected type ``4 = 5``
108+with the type of ``Refl``, ``x = x``, notice that a solution requires
109+that ``x`` be both ``4`` and ``5``, and therefore fail.
110+
111+Since type checking involves reduction to normal form, we can write the
112+following equalities directly:
113+
114+.. code-block:: idris
115+
116+ twoplustwo_eq_four : 2 + 2 = 4
117+ twoplustwo_eq_four = Refl
118+
119+ plus_reduces_Z : (m : Nat) -> plus Z m = m
120+ plus_reduces_Z m = Refl
121+
122+ plus_reduces_Sk : (k, m : Nat) -> plus (S k) m = S (plus k m)
123+ plus_reduces_Sk k m = Refl
124+
125+Heterogeneous Equality
126+----------------------
127+
128+Equality in Idris is *heterogeneous*, meaning that we can even propose
129+equalities between values in different types:
130+
131+.. code-block:: idris
132+
133+ idris_not_php : 2 = "2"
134+
135+Obviously, in Idris the type ``2 = "2"`` is uninhabited, and one might
136+wonder why it is useful to be able to propose equalities between values
137+in different types. However, with dependent types, such equalities can
138+arise naturally. For example, if two vectors are equal, their lengths
139+must be equal:
140+
141+.. code-block:: idris
142+
143+ vect_eq_length : (xs : Vect n a) -> (ys : Vect m a) ->
144+ (xs = ys) -> n = m
145+
146+In the above declaration, ``xs`` and ``ys`` have different types because
147+their lengths are different, but we would still like to draw a
148+conclusion about the lengths if they happen to be equal. We can define
149+``vect_eq_length`` as follows:
150+
151+.. code-block:: idris
152+
153+ vect_eq_length xs xs Refl = Refl
154+
155+By matching on ``Refl`` for the third argument, we know that the only
156+valid value for ``ys`` is ``xs``, because they must be equal, and
157+therefore their types must be equal, so the lengths must be equal.
158+
159+Alternatively, we can put an underscore for the second ``xs``, since
160+there is only one value which will type check:
161+
162+.. code-block:: idris
163+
164+ vect_eq_length xs _ Refl = Refl
165+
166+Properties of ``plus``
167+----------------------
168+
169+Using the ``(=)`` type, we can now state the properties of ``plus``
170+given above as Idris type declarations:
171+
172+.. code-block:: idris
173+
174+ plus_commutes : (n, m : Nat) -> plus n m = plus m n
175+ plus_assoc : (n, m, p : Nat) -> plus n (plus m p) = plus (plus n m) p
176+
177+Both of these properties (and many others) are proved for natural number
178+addition in the Idris standard library, using ``(+)`` from the ``Num``
179+type class rather than using ``plus`` directly. They have the names
180+``plusCommutative`` and ``plusAssociative`` respectively.
181+
182+In the remainder of this tutorial, we will explore several different
183+ways of proving ``plus_commutes`` (or, to put it another way, writing
184+the function.) We will also discuss how to use such equality proofs, and
185+see where the need for them arises in practice.
186+
187+.. [1]
188+ This is known as the Curry-Howard correspondence 
docs/reference/documenting.rstnew file+135
@@ -0,0 +1,135 @@
1+.. _sect-documenting:
2+
3+======================
4+Documenting Idris Code
5+======================
6+
7+Idris documentation comes in two major forms: comments, which exist
8+for a reader’s edification and are ignored by the compiler, and inline
9+API documentation, which the compiler parses and stores for future
10+reference. To consult the documentation for a declaration ``f``, write
11+``:doc f`` at the REPL or use the appropriate command in your editor
12+(``C-c C-d`` in Emacs, in Vim).
13+
14+Comments
15+--------
16+
17+Use comments to explain why code is written the way that it
18+is. Idris’s comment syntax is the same as that of Haskell: lines
19+beginning with ``--`` are comments, and regions bracketed by ``{-``
20+and ``-}`` are comments even if they extend across multiple
21+lines. These can be used to comment out lines of code or provide
22+simple documentation for the readers of Idris code.
23+
24+Inline Documentation
25+--------------------
26+
27+Idris also supports a comprehensive and rich inline syntax for Idris
28+code to be generated. This syntax also allows for named parameters and
29+variables within type signatures to be individually annotated using a
30+syntax similar to Javadoc parameter annotations.
31+
32+Documentation always comes before the declaration being documented.
33+Inline documentation applies to either top-level declarations or to
34+constructors. Documentation for specific arguments to constructors, type
35+constructors, or functions can be associated with these arguments using
36+their names.
37+
38+The inline documentation for a declaration is an unbroken string of
39+lines, each of which begins with ``|||`` (three pipe symbols). The
40+first paragraph of the documentation is taken to be an overview, and
41+in some contexts, only this overview will be shown. After the
42+documentation for the declaration as a whole, it is possible to
43+associate documetation with specific named parameters, which can
44+either be explicitly name or the results of converting free variables
45+to implicit parameters. Annotations are the same as with Javadoc
46+annotations, that is for the named parameter ``(n : T)``, the
47+corresponding annotation is ``||| @ n Some description`` that is
48+placed before the declaration.
49+
50+Documentation is written in Markdown, though not all contexts will
51+display all possible formatting (for example, images are not displayed
52+when viewing documentation in the REPL, and only some terminals render
53+italics correctly). A comprehensive set of examples is given below.
54+
55+.. code-block:: idris
56+
57+
58+ ||| Modules can also be documented.
59+ module Docs
60+
61+ ||| Add some numbers.
62+ |||
63+ ||| Addition is really great. This paragraph is not part of the overview.
64+ ||| Still the same paragraph. Lists are also nifty:
65+ ||| * Really nifty!
66+ ||| * Yep!
67+ ||| * The name `add` is a **bold** choice
68+ ||| @ n is the recursive param
69+ ||| @ m is not
70+ add : (n, m : Nat) -> Nat
71+ add Z m = m
72+ add (S n) m = S (add n m)
73+
74+
75+ ||| Append some vectors
76+ ||| @ a the contents of the vectors
77+ ||| @ xs the first vector (recursive param)
78+ ||| @ ys the second vector (not analyzed)
79+ appendV : (xs : Vect n a) -> (ys : Vect m a) -> Vect (add n m) a
80+ appendV [] ys = ys
81+ appendV (x::xs) ys = x :: appendV xs ys
82+
83+ ||| Here's a simple datatype
84+ data Ty =
85+ ||| Unit
86+ UNIT |
87+ ||| Functions
88+ ARR Ty Ty
89+
90+ ||| Points to a place in a typing context
91+ data Elem : Vect n Ty -> Ty -> Type where
92+ Here : {ts : Vect n Ty} -> Elem (t::ts) t
93+ There : {ts : Vect n Ty} -> Elem ts t -> Elem (t'::ts) t
94+
95+ ||| A more interesting datatype
96+ ||| @ n the number of free variables
97+ ||| @ ctxt a typing context for the free variables
98+ ||| @ ty the type of the term
99+ data Term : (ctxt : Vect n Ty) -> (ty : Ty) -> Type where
100+
101+ ||| The consructor of the unit type
102+ ||| More comment
103+ ||| @ ctxt the typing context
104+ UnitCon : {ctxt : Vect n Ty} -> Term ctxt UNIT
105+
106+ ||| Function application
107+ ||| @ f the function to apply
108+ ||| @ x the argument
109+ App : {ctxt : Vect n Ty} -> (f : Term ctxt (ARR t1 t2)) -> (x : Term ctxt t1) -> Term ctxt t2
110+
111+ ||| Lambda
112+ ||| @ body the function body
113+ Lam : {ctxt : Vect n Ty} -> (body : Term (t1::ctxt) t2) -> Term ctxt (ARR t1 t2)
114+
115+ ||| Variables
116+ ||| @ i de Bruijn index
117+ Var : {ctxt : Vect n Ty} -> (i : Elem ctxt t) -> Term ctxt t
118+
119+ ||| A computation that may someday finish
120+ codata Partial : Type -> Type where
121+
122+ ||| A finished computation
123+ ||| @ value the result
124+ Now : (value : a) -> Partial a
125+
126+ ||| A not-yet-finished computation
127+ ||| @ rest the remaining work
128+ Later : (rest : Partial a) -> Partial a
129+
130+ ||| We can document records just like normal data
131+ record Yummy : Type where
132+
133+ ||| Make a yummy
134+ ||| @ food what to eat
135+ MkYummy : (food : String) -> Yummy
docs/reference/erasure.rstnew file+501
@@ -0,0 +1,501 @@
1+Erasure By Usage Analysis
2+=========================
3+
4+This work stems from this `feature proposal
5+<https://github.com/idris-lang/Idris-dev/wiki/Egg-%232%3A-Erasure-annotations>`__
6+(obsoleted by this page). Beware that the information in the proposal
7+is out of date — and sometimes even in direct contradiction with the
8+eventual implementation.
9+
10+Motivation
11+----------
12+
13+Traditional dependently typed languages (Agda, Coq) are good at
14+erasing *proofs* (either via irrelevance or an extra universe).
15+
16+.. code-block:: idris
17+
18+ half : (n : Nat) -> Even n -> Nat
19+ half Z EZ = Z
20+ half (S (S n)) (ES pf) = S (half n pf)
21+
22+For example, in the above snippet, the second argument is a proof,
23+which is used only to convince the compiler that the function is
24+total. This proof is never inspected at runtime and thus can be
25+erased. In this case, the mere existence of the proof is sufficient
26+and we can use irrelevance-related methods to achieve erasure.
27+
28+However, sometimes we want to erase *indices* and this is where the
29+traditional approaches stop being useful, mainly for reasons described
30+in the `original proposal
31+<https://github.com/idris-lang/Idris-dev/wiki/Egg-%232%3A-Erasure-annotations#prop-is-cumbersome-coq>`__.
32+
33+.. code-block:: idris
34+
35+ uninterleave : {n : Nat} -> Vect (n * 2) a -> (Vect n a, Vect n a)
36+ uninterleave [] = ([] , [])
37+ uninterleave (x :: y :: rest) with (unzipPairs rest)
38+ | (xs, ys) = (x :: xs, y :: ys)
39+
40+Notice that in this case, the second argument is the important one and
41+we would like to get rid of the ``n`` instead, although the shape of
42+the program is generally the same as in the previous case.
43+
44+There are methods described by Brady, McBride and McKinna in [BMM04]_
45+to remove the indices from data structures, exploiting the fact that
46+functions operating on them either already have a copy of the
47+appropriate index or the index can be quickly reconstructed if needed.
48+However, we often want to erase the indices altogether, from the whole
49+program, even in those cases where reconstruction is not possible.
50+
51+The following two sections describe two cases where doing so improves
52+the runtime performance asymptotically.
53+
54+Binary numbers
55+~~~~~~~~~~~~~~
56+
57+- O(n) instead of O(log n)
58+
59+Consider the following ``Nat``-indexed type family representing binary
60+numbers:
61+
62+.. code-block:: idris
63+
64+ data Bin : Nat -> Type where
65+ N : Bin 0
66+ O : {n : Nat} -> Bin n -> Bin (0 + 2*n)
67+ I : {n : Nat} -> Bin n -> Bin (1 + 2*n)
68+
69+These are supposed to be (at least asymptotically) fast and
70+memory-efficient because their size is logarithmic compared to the
71+numbers they represent.
72+
73+Unfortunately this is not the case. The problem is that these binary
74+numbers still carry the *unary* indices with them, performing
75+arithmetic on the indices whenever arithmetic is done on the binary
76+numbers themselves. Hence the real representation of the number 15
77+looks like this:
78+
79+::
80+
81+ I -> I -> I -> I -> N
82+ S S S Z
83+ S S Z
84+ S S
85+ S Z
86+ S
87+ S
88+ S
89+ Z
90+
91+The used memory is actually *linear*, not logarithmic and therefore we
92+cannot get below O(n) with time complexities.
93+
94+One could argue that Idris in fact compiles ``Nat`` via GMP but
95+that's a moot point for two reasons:
96+
97++ First, whenever we try to index our datastructures with anything
98+ else than ``Nat``, the compiler is not going to come to the rescue.
99+
100++ Second, even with ``Nat``, the GMP integers are *still* there and
101+ they slow the runtime down.
102+
103+This ought not to be the case since the ``Nat`` are never used at
104+runtime and they are only there for typechecking purposes. Hence we
105+should get rid of them and get runtime code similar to what a idris
106+programmer would write.
107+
108+U-views of lists
109+~~~~~~~~~~~~~~~~
110+
111+- O(n^2) instead of O(n)
112+
113+Consider the type of U-views of lists:
114+
115+.. code-block:: idris
116+
117+ data U : List a -> Type where
118+ nil : U []
119+ one : (z : a) -> U [z]
120+ two : {xs : List a} -> (x : a) -> (u : U xs) -> (y : a) -> U (x :: xs ++ [y])
121+
122+For better intuition, the shape of the U-view of
123+``[x0,x1,x2,z,y2,y1,y0]`` looks like this:
124+
125+::
126+
127+ x0 y0 (two)
128+ x1 y1 (two)
129+ x2 y1 (two)
130+ z (one)
131+
132+When recursing over this structure, the values of ``xs`` range over
133+``[x0,x1,x2,z,y2,y1,y0]``, ``[x1,x2,z,y2,y1]``, ``[x2,z,y2]``,
134+``[z]``. No matter whether these lists are stored or built on demand,
135+they take up a quadratic amount of memory (because they cannot share
136+nodes), and hence it takes a quadratic amount of time just to build
137+values of this index alone.
138+
139+But the reasonable expectation is that operations with U-views take
140+linear time — so we need to erase the index ``xs`` if we want to
141+achieve this goal.
142+
143+Changes to Idris
144+----------------
145+
146+Usage analysis is run at every compilation and its outputs are used
147+for various purposes. This is actually invisible to the user but it's
148+a relatively big and important change, which enables the new features.
149+
150+Everything that is found to be unused is erased. No annotations are
151+needed, just don't use the thing and it will vanish from the generated
152+code. However, if you wish, you can use the dot annotations to get a
153+warning if the thing is accidentally used.
154+
155+"Being used" in this context means that the value of the "thing" may
156+influence run-time behaviour of the program. (More precisely, it is
157+not found to be irrelevant to the run-time behaviour by the usage
158+analysis algorithm.)
159+
160+"Things" considered for removal by erasure include:
161+
162+* function arguments
163+
164+* data constructor fields (including record fields and dictionary
165+ fields of class instances)
166+
167+For example, ``Either`` often compiles to the same runtime
168+representation as ``Bool``. Constructor field removal sometimes
169+combines with the newtype optimisation to have quite a strong effect.
170+
171+There is a new compiler option ``--warnreach``, which will enable
172+warnings coming from erasure. Since we have full usage analysis, we
173+can compile even those programs that violate erasure annotations --
174+it's just that the binaries may run slower than expected. The warnings
175+will be enabled by default in future versions of Idris (and possibly
176+turned to errors). However, in this transitional period, we chose to
177+keep them on-demand to avoid confusion until better documentation is
178+written.
179+
180+Case-tree elaboration tries to avoid using dotted "things" whenever
181+possible. (NB. This is not yet perfect and it's being worked on:
182+https://gist.github.com/ziman/10458331)
183+
184+Postulates are no longer required to be collapsible. They are now
185+required to be *unused* instead.
186+
187+Changes to the language
188+-----------------------
189+
190+You can use dots to mark fields that are not intended to be used at
191+runtime.
192+
193+.. code-block:: idris
194+
195+ data Bin : Nat -> Type where
196+ N : Bin 0
197+ O : .{n : Nat} -> Bin n -> Bin (0 + 2*n)
198+ I : .{n : Nat} -> Bin n -> Bin (1 + 2*n)
199+
200+If these fields are found to be used at runtime, the dots will trigger
201+a warning (with ``--warnreach``).
202+
203+Note that free (unbound) implicits are dotted by default so, for
204+example, the constructor ``O`` can be defined as:
205+
206+.. code-block:: idris
207+
208+ O : Bin n -> Bin (0 + 2*n)
209+
210+and this is actually the preferred form.
211+
212+If you have a free implicit which is meant to be used at runtime, you
213+have to change it into an (undotted) ``{bound : implicit}``.
214+
215+You can also put dots in types of functions to get more guarantees.
216+
217+.. code-block:: idris
218+
219+ half : (n : Nat) -> .(pf : Even n) -> Nat
220+
221+and free implicits are automatically dotted here, too.
222+
223+What it means
224+-------------
225+
226+Dot annotations serve two purposes:
227+
228+* influence case-tree elaboration to avoid dotted variables
229+
230+* trigger warnings when a dotted variable is used
231+
232+However, there's no direct connection between being dotted and being
233+erased. The compiler erases everything it can, dotted or not. The dots
234+are there mainly to help the programmer (and the compiler) refrain
235+from using the values they want to erase.
236+
237+How to use it
238+-------------
239+
240+Ideally, few or no extra annotations are needed -- in practice, it
241+turns out that having free implicits automatically dotted is enough to
242+get good erasure.
243+
244+Therefore, just compile with ``--warnreach`` to see warnings if
245+erasure cannot remove parts of the program.
246+
247+However, those programs that have been written without runtime
248+behaviour in mind, will need some help to get in the form that
249+compiles to a reasonable binary. Generally, it's sufficient to follow
250+erasure warnings (which may be sometimes unhelpful at the moment).
251+
252+Benchmarks
253+----------
254+
255+- source: https://github.com/ziman/idris-benchmarks
256+- results: http://ziman.functor.sk/erasure-bm/
257+
258+It can be clearly seen that asymptotics are improved by erasure.
259+
260+Shortcomings
261+------------
262+
263+You can't get warnings in libraries because usage analysis starts from
264+``Main.main``. This will be solved by the planned ``%default_usage``
265+pragma.
266+
267+Usage warnings are quite bad and unhelpful at the moment. We should
268+include more information and at least translate argument numbers to
269+their names.
270+
271+There is no decent documentation yet. This wiki page is the first one.
272+
273+There is no generally accepted terminology. We switch between
274+"dotted", "unused", "erased", "irrelevant", "inaccessible", while each
275+has a slightly different meaning. We need more consistent and
276+understandable naming.
277+
278+If the same type is used in both erased and non-erased context, it
279+will retain its fields to accomodate the least common denominator --
280+the non-erased context. This is particularly troublesome in the case
281+of the type of (dependent) pairs, where it actually means that no
282+erasure would be performed. We should probably locate disjoint uses of
283+data types and split them into "sub-types". There are three different
284+flavours of dependent types now: ``Sigma`` (nothing erased),
285+``Exists`` (first component erased), ``Subset`` (second component
286+erased).
287+
288+Case-tree building does not avoid dotted values coming from
289+pattern-matched constructors (https://gist.github.com/ziman/10458331).
290+This is to be fixed soon. (Fixed.)
291+
292+Higher-order function arguments and opaque functional variables are
293+considered to be using all their arguments. To work around this, you
294+can force erasure via the type system, using the ``Erased`` wrapper:
295+https://github.com/idris-lang/Idris-dev/blob/master/libs/base/Data/Erased.idr
296+
297+Typeclass methods are considered to be using the union of all their
298+implementations. In other words, an argument of a method is unused
299+only if it is unused in every implementation of the method that occurs
300+in the program.
301+
302+Planned features
303+----------------
304+
305+- Fixes to the above shortcomings in general.
306+
307+- Improvements to the case-tree elaborator so that it properly avoids
308+ dotted fields of data constructors. Done.
309+
310+- Compiler pragma ``%default_usage used/unused`` and per-function
311+ overrides ``used`` and ``unused``, which allow the programmer to
312+ mark the return value of a function as used, even if the function
313+ is not used in ``main`` (which is the case when writing library
314+ code). These annotations will help library writers discover usage
315+ violations in their code before it is actually published and used
316+ in compiled programs.
317+
318+Troubleshooting
319+---------------
320+
321+My program is slower
322+~~~~~~~~~~~~~~~~~~~~
323+
324+The patch introducing erasure by usage analysis also disabled some
325+optimisations that were in place before; these are subsumed by the new
326+erasure. However, in some erasure-unaware programs, where erasure by
327+usage analysis does not exercise its full potential (but the old
328+optimisations would have worked), certain slowdown may be observed (up
329+to ~10% according to preliminary benchmarking), due to retention and
330+computation of information that should not be necessary at runtime.
331+
332+A simple check whether this is the case is to compile with
333+``--warnreach``. If you see warnings, there is some unnecessary code
334+getting compiled into the binary.
335+
336+The solution is to change the code so that there are no warnings.
337+
338+Usage warnings are unhelpful
339+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
340+
341+This is a known issue and we are working on it. For now, see the section
342+`How to read and resolve erasure
343+warnings <#how-to-read-and-resolve-erasure-warnings>`__.
344+
345+There should be no warnings in this function
346+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
347+
348+A possible cause is non-totality of the function (more precisely,
349+non-coverage). If a function is non-covering, the program needs to
350+inspect all arguments in order to detect coverage failures at runtime.
351+Since the function inspects all its arguments, nothing can be erased
352+and this may transitively cause usage violations. The solution is to
353+make the function total or accept the fact that it will use its
354+arguments and remove some dots from the appropriate constructor fields
355+and function arguments. (Please note that this is not a shortcoming of
356+erasure and there is nothing we can do about it.)
357+
358+Another possible cause is the currently imperfect case-tree
359+elaboration, which does not avoid dotted constructor fields (see
360+https://gist.github.com/ziman/10458331). You can either rephrase the
361+function or wait until this is fixed, hopefully soon. Fixed.
362+
363+The compiler refuses to recognise this thing as erased
364+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
365+
366+You can force anything to be erased by wrapping it in the ``Erased``
367+monad. While this program triggers usage warnings,
368+
369+.. code-block:: idris
370+
371+ f : (g : Nat -> Nat) -> .(x : Nat) -> Nat
372+ f g x = g x -- WARNING: g uses x
373+
374+the following program does not:
375+
376+.. code-block:: idris
377+
378+ f : (g : Erased Nat -> Nat) -> .(x : Nat) -> Nat
379+ f g x = g (Erase x) -- OK
380+
381+How to read and resolve erasure warnings
382+----------------------------------------
383+
384+Example 1
385+~~~~~~~~~
386+
387+Consider the following program:
388+
389+.. code-block:: idris
390+
391+ vlen : Vect n a -> Nat
392+ vlen {n = n} xs = n
393+
394+ sumLengths : List (Vect n a) -> Nat
395+ sumLengths [] = 0
396+ sumLengths (v :: vs) = vlen v + sumLengths vs
397+
398+ main : IO ()
399+ main = print . sumLengths $ [[0,1],[2,3]]
400+
401+When you compile it using ``--warnreach``, there is one warning:
402+
403+.. code-block:: idris
404+
405+ Main.sumLengths: inaccessible arguments reachable:
406+ n (no more information available)
407+
408+The warning does not contain much detail at this point so we can try
409+compiling with ``--dumpcases cases.txt`` and look up the compiled
410+definition in ``cases.txt``:
411+
412+.. code-block:: idris
413+
414+ Main.sumLengths {e0} {e1} {e2} =
415+ case {e2} of
416+ | Prelude.List.::({e6}) => LPlus (ATInt ITBig)({e0}, Main.sumLengths({e0}, ____, {e6}))
417+ | Prelude.List.Nil() => 0
418+
419+The reason for the warning is that ``sumLengths`` calls ``vlen``, which
420+gets inlined. The second clause of ``sumLengths`` then accesses the
421+variable ``n``, compiled as ``{e0}``. Since ``n`` is a free implicit, it
422+is automatically considered dotted and this triggers the warning.
423+
424+A solution would be either making the argument ``n`` a bound implicit
425+parameter to indicate that we wish to keep it at runtime,
426+
427+.. code-block:: idris
428+
429+ sumLengths : {n : Nat} -> List (Vect n a) -> Nat
430+
431+or fixing ``vlen`` to not use the index:
432+
433+.. code-block:: idris
434+
435+ vlen : Vect n a -> Nat
436+ vlen [] = Z
437+ vlen (x :: xs) = S (vlen xs)
438+
439+Which solution is appropriate depends on the usecase.
440+
441+Example 2
442+~~~~~~~~~
443+
444+Consider the following program manipulating value-indexed binary
445+numbers.
446+
447+.. code-block:: idris
448+
449+ data Bin : Nat -> Type where
450+ N : Bin Z
451+ O : Bin n -> Bin (0 + n + n)
452+ I : Bin n -> Bin (1 + n + n)
453+
454+ toN : (b : Bin n) -> Nat
455+ toN N = Z
456+ toN (O {n} bs) = 0 + n + n
457+ toN (I {n} bs) = 1 + n + n
458+
459+ main : IO ()
460+ main = print . toN $ I (I (O (O (I N))))
461+
462+In the function ``toN``, we attempted to "cheat" and instead of
463+traversing the whole structure, we just projected the value index ``n``
464+out of constructors ``I`` and ``O``. However, this index is a free
465+implicit, therefore it is considered dotted.
466+
467+Inspecting it then produces the following warnings when compiling with
468+``--warnreach``:
469+
470+.. code-block:: idris
471+
472+ Main.I: inaccessible arguments reachable:
473+ n from Main.toN arg# 1
474+ Main.O: inaccessible arguments reachable:
475+ n from Main.toN arg# 1
476+
477+We can see that the argument ``n`` of both ``I`` and ``O`` is used in
478+the function ``toN``, argument 1.
479+
480+At this stage of development, warnings only contain argument numbers,
481+not names; this will hopefully be fixed. When numbering arguments, we
482+go from 0, taking free implicits first, left-to-right; then the bound
483+arguments. The function ``toN`` has therefore in fact two arguments:
484+``n`` (argument 0) and ``b`` (argument 1). And indeed, as the warning
485+says, we project the dotted field from ``b``.
486+
487+Again, one solution is to fix the function ``toN`` to calculate its
488+result honestly; the other one is to accept that we carry a ``Nat``
489+with every constructor of ``Bin`` and make it a bound implicit:
490+
491+.. code-block:: idris
492+
493+ O : {n : Nat} -> Bin n -> Bin (0 + n + n)
494+ I : {n : Nat} -> bin n -> Bin (1 + n + n)
495+
496+References
497+----------
498+
499+.. [BMM04] Edwin Brady, Conor McBride, James McKinna: `Inductive
500+ families need not store their indices
501+ <http://citeseerx.ist.psu.edu/viewdoc/summary;jsessionid=1F796FCF0F2C4C535FC70F62BE2FB821?doi=10.1.1.62.3849>`__
docs/reference/ffi.rstnew file+277
@@ -0,0 +1,277 @@
1+New Foreign Function Interface
2+==============================
3+
4+.. sectionauthor:: Edwin Brady
5+
6+Ever since Idris has had multiple backends compiling to different
7+target languages on potentially different platforms, we have had the
8+problem that the foreign function interface (FFI) was written under
9+the assumption of compiling to C. As a result, it has been hard to
10+write generic code for multiple targets, or even to be sure that if
11+code compiles that it will run on the expected target.
12+
13+As of 0.9.17, Idris will have a new foreign function interface (FFI)
14+which is aware of multiple targets. Users who are working with the
15+default code generator can happily continue writing programs as before
16+with no changes, but if you are writing bindings for an external
17+library, writing a back end, or working with a non-C back end, there
18+are some things you will need to be aware of, which this page
19+describes.
20+
21+The ``IO'`` monad, and ``main``
22+-------------------------------
23+
24+The ``IO`` monad exists as before, but is now specific to the C
25+backend (or, more precisely, any backend whose foreign function calls
26+are compatible with C.) Additionally, there is now an ``IO'`` monad,
27+which is parameterised over a FFI descriptor:
28+
29+.. code-block:: idris
30+
31+ data IO' : (lang : FFI) -> Type -> Type
32+
33+The Prelude defines two FFI descriptors which are imported
34+automatically, for C and JavaScript/Node, and defines ``IO`` to use
35+the C FFI and ``JS_IO`` to use the JavaScript FFI:
36+
37+.. code-block:: idris
38+
39+ FFI_C : FFI
40+ FFI_JS : FFI
41+
42+ IO : Type -> Type
43+ IO a = IO' FFI_C a
44+
45+ JS_IO : Type -> Type
46+ JS_IO a = IO' FFI_JS a
47+
48+As before, the entry point to an Idris program is ``main``, but the
49+type of ``main`` can now be any instance of ``IO'``, e.g. the
50+following are both valid:
51+
52+.. code-block:: idris
53+
54+ main : IO ()
55+ main : JS_IO ()
56+
57+The FFI descriptor includes details about which types can be
58+marshalled between the foreign language and Idris, and the "target" of
59+a foreign function call (typically just a String representation of the
60+function's name, but potentially something more complicated such as an
61+external library file or even a URL).
62+
63+FFI descriptors
64+---------------
65+
66+An FFI descriptor is a record containing a predicate which holds when
67+a type can be marshalled, and the type of the target of a foreign
68+call:
69+
70+.. code-block:: idris
71+
72+ record FFI : Type where
73+ MkFFI : (ffi_types : Type -> Type) ->
74+ (ffi_fn : Type) -> FFI
75+
76+For C, this is:
77+
78+.. code-block:: idris
79+
80+ -- Supported C integer types
81+ data C_IntTypes : Type -> Type where
82+ C_IntChar : C_IntTypes Char
83+ C_IntNative : C_IntTypes Int
84+ ... -- more integer types
85+
86+ -- Supported C foreign types
87+ data C_Types : Type -> Type where
88+ C_Str : C_Types String
89+ C_Float : C_Types Float
90+ C_Ptr : C_Types Ptr
91+ C_MPtr : C_Types ManagedPtr
92+ C_Unit : C_Types ()
93+ C_Any : C_Types (Raw a)
94+ C_IntT : C_IntTypes i -> C_Types i
95+
96+ FFI_C : FFI
97+ FFI_C = MkFFI C_Types
98+ String -- the name of the C function
99+
100+Foreign calls
101+-------------
102+
103+To call a foreign function, the ``foreign`` function is used. For
104+example:
105+
106+.. code-block:: idris
107+
108+ do_fopen : String -> String -> IO Ptr
109+ do_fopen f m
110+ = foreign FFI_C "fileOpen" (String -> String -> IO Ptr) f m
111+
112+The ``foreign`` function takes an FFI description, a function name (the
113+type is given by the ``ffi_fn`` field of ``FFI_C`` here), and a function
114+type, which gives the expected types of the remaining arguments. Here,
115+we're calling an external function ``fileOpen`` which takes, in the C, a
116+``char*`` file name, a ``char*`` mode, and returns a file pointer. It is
117+the job of the C back end to convert Idris ``String`` to C ``char*``
118+and vice versa.
119+
120+The argument types and return type given here must be present in the
121+``fn_types`` predicate of the ``FFI_C`` description for the foreign
122+call to be valid.
123+
124+**Note** The arguments to ``foreign`` *must* be known at compile time,
125+because the foreign calls are generated statically. The ``%inline``
126+directive on a function can be used to give hints to help this, for
127+example a shorthand for calling external JavaScript functions:
128+
129+.. code-block:: idris
130+
131+ %inline
132+ jscall : (fname : String) -> (ty : Type) ->
133+ {auto fty : FTy FFI_JS [] ty} -> ty
134+ jscall fname ty = foreign FFI_JS fname ty
135+
136+FFI implementation
137+~~~~~~~~~~~~~~~~~~
138+
139+In order to write bindings to external libraries, the details of how
140+``foreign`` works are unnecessary --- you simply need to know that
141+``foreign`` takes an FFI descriptor, the function name, and its
142+type. It is instructive to look a little deeper, however:
143+
144+The type of ``foreign`` is as follows:
145+
146+.. code-block:: idris
147+
148+ foreign : (ffi : FFI)
149+ -> (fname : ffi_fn f)
150+ -> (ty : Type)
151+ -> {auto fty : FTy ffi [] ty}
152+ -> ty
153+
154+The important argument here is the implicit ``fty``, which contains a
155+proof (``FTy``) that the given type is valid according to the FFI
156+description ``ffi``:
157+
158+.. code-block:: idris
159+
160+ data FTy : FFI -> List Type -> Type -> Type where
161+ FRet : ffi_types f t -> FTy f xs (IO' f t)
162+ FFun : ffi_types f s -> FTy f (s :: xs) t -> FTy f xs (s -> t)
163+
164+Notice that this uses the ``ffi_types`` field of the FFI descriptor
165+--- these arguments to ``FRet`` and ``FFun`` give explicit proofs that
166+the type is valid in this FFI. For example, the above ``do_fopen``
167+builds the following implicit proof as the ``fty`` argument to
168+``foreign``:
169+
170+.. code-block:: idris
171+
172+ FFun C_Str (FFun C_Str (FRet C_Ptr))
173+
174+Compiling foreign calls
175+-----------------------
176+
177+(This section assumes some knowledge of the Idris internals.)
178+
179+When writing a back end, we now need to know how to compile
180+``foreign``. We'll skip the details here of how a ``foreign`` call
181+reaches the intermediate representation (the IR), though you can look
182+in ``IO.idr`` in the ``prelude`` package to see a bit more detail ---
183+a ``foreign`` call is implemented by the primitive function
184+``mkForeignPrim``. The important part of the IR as defined in
185+``Lang.hs`` is the following constructor:
186+
187+.. code-block:: idris
188+
189+ data LExp = ...
190+ | LForeign FDesc -- Function descriptor
191+ FDesc -- Return type descriptor
192+ [(FDesc, LExp)]
193+
194+So, a ``foreign`` call appears in the IR as the ``LForeign``
195+constructor, which takes a function descriptor (of a type given by the
196+``ffi_fn`` field in the FFI descriptor), a return type descriptor
197+(given by an application of ``FTy``), and a list of arguments with
198+type descriptors (also given by an application of ``FTy``).
199+
200+An ``FDesc`` describes an application of a name to some arguments, and
201+is really just a simplified subset of an ``LExp``:
202+
203+.. code-block:: idris
204+
205+ data FDesc = FCon Name
206+ | FStr String
207+ | FUnknown
208+ | FApp Name [FDesc]
209+
210+There are corresponding structures in the lower level IRs, such as the
211+defunctionalised, simplified and bytecode forms.
212+
213+Our ``do_fopen`` example above arrives in the ``LExp`` form as:
214+
215+.. code-block:: idris
216+
217+ LForeign (FStr "fileOpen") (FCon (sUN "C_Ptr"))
218+ [(FCon (sUN "C_Str"), f), (FCon (sUN "C_Str"), m)]
219+
220+(Assuming that ``f`` and ``m`` stand for the ``LExp`` representations
221+of the arguments.) This information should be enough for any back end
222+to marshal the arguments and return value appropriately.
223+
224+.. note::
225+
226+ When processing ``FDesc``, be aware that there may be implicit
227+ arguments, which have not been erased. For example, ``C_IntT`` has
228+ an implicit argument ``i``, so will appear in an ``FDesc`` as
229+ something of the form ``FApp (sUN "C_IntT") [i, t]`` where ``i`` is
230+ the implicit argument (which can be ignored) and ``t`` is the
231+ descriptor of the integer type. See ``CodegenC.hs``, specifically
232+ the function ``toFType``, to see how this works in practice.
233+
234+JavaScript FFI descriptor
235+~~~~~~~~~~~~~~~~~~~~~~~~~
236+
237+The JavaScript FFI descriptor is a little more complex, because the
238+JavaScript FFI supports marshalling functions. It is defined as
239+follows:
240+
241+.. code-block:: idris
242+
243+ mutual
244+ data JsFn t = MkJsFn t
245+
246+ data JS_IntTypes : Type -> Type where
247+ JS_IntChar : JS_IntTypes Char
248+ JS_IntNative : JS_IntTypes Int
249+
250+ data JS_FnTypes : Type -> Type where
251+ JS_Fn : JS_Types s -> JS_FnTypes t -> JS_FnTypes (s -> t)
252+ JS_FnIO : JS_Types t -> JS_FnTypes (IO' l t)
253+ JS_FnBase : JS_Types t -> JS_FnTypes t
254+
255+ data JS_Types : Type -> Type where
256+ JS_Str : JS_Types String
257+ JS_Float : JS_Types Float
258+ JS_Ptr : JS_Types Ptr
259+ JS_Unit : JS_Types ()
260+ JS_FnT : JS_FnTypes a -> JS_Types (JsFn a)
261+ JS_IntT : JS_IntTypes i -> JS_Types i
262+
263+The reason for wrapping function types in a ``JsFn`` is to help the
264+proof search when building ``FTy``. We hope to improve proof search
265+eventually, but for the moment it works much more reliably if the
266+indices are disjoint! An example of using this appears in `IdrisScript
267+<https://github.com/idris-hackers/IdrisScript>`__ when setting
268+timeouts:
269+
270+.. code-block:: idris
271+
272+ setTimeout : (() -> JS_IO ()) -> (millis : Int) -> JS_IO Timeout
273+ setTimeout f millis = do
274+ timeout <- jscall "setTimeout(%0, %1)"
275+ (JsFn (() -> JS_IO ()) -> Int -> JS_IO Ptr)
276+ (MkJsFn f) millis
277+ return $ MkTimeout timeout
docs/reference/index.rstnew file+26
@@ -0,0 +1,26 @@
1+.. _reference-index:
2+
3+###################
4+Language Reference
5+###################
6+
7+This is the reference guide for the Idris Language.
8+It documents the language specification and internals.
9+This will tell you how Idris works, for using it you should read the Idris Tutorial.
10+
11+.. note::
12+ The documentation for Idris has been published under the Creative
13+ Commons CC0 License. As such to the extent possible under law, *The
14+ Idris Community* has waived all copyright and related or neighboring
15+ rights to Documentation for Idris.
16+
17+ More information concerning the CC0 can be found online at: http://creativecommons.org/publicdomain/zero/1.0/
18+
19+
20+.. toctree::
21+ :maxdepth: 1
22+
23+ documenting
24+ uniqueness-types
25+ ffi
26+ erasure
docs/reference/uniqueness-types.rstnew file+251
@@ -0,0 +1,251 @@
1+Uniqueness Types
2+================
3+
4+Uniqueness Types are an experimental feature available from Idris
5+0.9.15. A value with a unique type is guaranteed to have *at most one*
6+reference to it at run-time, which means that it can safely be updated
7+in-place, reducing the need for memory allocation and garbage
8+collection. The motivation is that we would like to be able to write
9+reactive systems, programs which run in limited memory environments,
10+device drivers, and any other system with hard real-time requirements,
11+ideally while giving up as little high level conveniences as possible.
12+
13+They are inspired by linear types, `Uniqueness Types
14+<https://en.wikipedia.org/wiki/Uniqueness_type>`__ in the `Clean
15+<http://wiki.clean.cs.ru.nl/Clean>`__ programming language, and
16+ownership types and borrowed pointers in the `Rust
17+<http://www.rust-lang.org/>`__ programming language.
18+
19+Some things we hope to be able to do eventually with uniqueness types
20+include:
21+
22+- Safe, pure, in-place update of arrays, lists, etc
23+- Provide guarantees of correct resource usage, state transitions, etc
24+- Provide guarantees that critical program fragments will *never*
25+ allocate
26+
27+Using Uniqueness
28+~~~~~~~~~~~~~~~~
29+
30+If ``x : T`` and ``T : UniqueType``, then there is at most one reference
31+to ``x`` at any time during run-time execution. For example, we can
32+declare the type of unique lists as follows:
33+
34+.. code-block:: idris
35+
36+ data UList : Type -> UniqueType
37+ Nil : UList a
38+ (::) : a -> UList a -> UList a
39+
40+If we have a value ``xs : UList a``, then there is at most one
41+reference to ``xs`` at run-time. The type checker preserves this
42+guarantee by ensuring that there is at most one reference to any value
43+of a unique type in a pattern clause. For example, the following
44+function definition would be valid:
45+
46+.. code-block:: idris
47+
48+ umap : (a -> b) -> UList a -> UList b
49+ umap f [] = []
50+ umap f (x :: xs) = f x :: umap f xs
51+
52+In the second clause, ``xs`` is a value of a unique type, and only
53+appears once on the right hand side, so this clause is valid. Not only
54+that, since we know there can be no other reference to the ``UList a``
55+argument, we can reuse its space for building the result! The compiler
56+is aware of this, and compiles this definition to an in-place update
57+of the list.
58+
59+The following function definition would not be valid (even assuming an
60+implementation of ``++``), however, since ``xs`` appears twice:
61+
62+.. code-block:: idris
63+
64+ dupList : UList a -> UList a
65+ dupList xs = xs ++ xs
66+
67+This would result in a shared pointer to ``xs``, so the typechecker
68+reports:
69+
70+.. code-block:: idris
71+
72+ unique.idr:12:5:Unique name xs is used more than once
73+
74+If we explicitly copy, however, the typechecker is happy:
75+
76+.. code-block:: idris
77+
78+ dup : UList a -> UList a
79+ dup [] = []
80+ dup (x :: xs) = x :: x :: dup xs
81+
82+Note that it's fine to use ``x`` twice, because ``a`` is a ``Type``,
83+rather than a ``UniqueType``.
84+
85+There are some other restrictions on where a ``UniqueType`` can
86+appear, so that the uniqueness property is preserved. In particular,
87+the type of the function type, ``(x : a) -> b`` depends on the type of
88+``a`` or ``b`` - if either is a ``UniqueType``, then the function type
89+is also a ``UniqueType``. Then, in a data declaration, if the type
90+constructor builds a ``Type``, then no constructor can have a
91+``UniqueType``. For example, the following definition is invalid,
92+since it would embed a unique value in a possible non-unique value:
93+
94+.. code-block:: idris
95+
96+ data BadList : UniqueType -> Type
97+ Nil : {a : UniqueType} -> BadList a
98+ (::) : {a : UniqueType} -> a -> BadList a -> BadList a
99+
100+Finally, types may be polymorphic in their uniqueness, to a limited
101+extent. Since ``Type`` and ``UniqueType`` are different types, we are
102+limited in how much we can use polymorphic functions on unique types.
103+For example, if we have function composition defined as follows:
104+
105+.. code-block:: idris
106+
107+ (.) : {a, b, c : Type} -> (b -> c) -> (a -> b) -> a -> c
108+ (.) f g x = f (g x)
109+
110+And we have some functions over unique types:
111+
112+.. code-block:: idris
113+
114+ foo : UList a -> UList b
115+ bar : UList b -> UList c
116+
117+Then we cannot compose ``foo`` and ``bar`` as ``bar . foo``, because
118+``UList`` does not compute a ``Type``! Instead, we can define
119+composition as follows:
120+
121+.. code-block:: idris
122+
123+ (.) : {a, b, c : Type*} -> (b -> c) -> (a -> b) -> a -> c
124+ (.) f g x = f (g x)
125+
126+The ``Type*`` type stands for either unique or non-unique types. Since
127+such a function may be passed a ``UniqueType``, any value of type
128+``Type*`` must also satisfy the requirement that it appears at most
129+once on the right hand side.
130+
131+Borrowed Types
132+~~~~~~~~~~~~~~
133+
134+It quickly becomes obvious when working with uniqueness types that
135+having only one reference at a time can be painful. For example, what
136+if we want to display a list before updating it?
137+
138+.. code-block:: idris
139+
140+ showU : Show a => UList a -> String
141+ showU xs = "[" ++ showU' xs ++ "]" where
142+ showU' : UList a -> String
143+ showU' [] = ""
144+ showU' [x] = show x
145+ showU' (x :: xs) = show x ++ ", " ++ showU' xs
146+
147+This is a valid definition of ``showU``, but unfortunately it consumes
148+the list! So the following function would be invalid:
149+
150+.. code-block:: idris
151+
152+ printAndUpdate : UList Int -> IO ()
153+ printAndUpdate xs = do putStrLn (showU xs)
154+ let xs' = umap (*2) xs -- xs no longer available!
155+ putStrLn (showU xs')
156+
157+Still, one would hope to be able to display a unique list without
158+problem, since it merely *inspects* the list; there are no updates. We
159+can achieve this, using the notion of *borrowing*. A Borrowed type is
160+a Unique type which can be inspected at the top level (by pattern
161+matching, or by *lending* to another function) but no further. This
162+ensures that the internals (i.e. the arguments to top level patterns)
163+will not be passed to any function which will update them.
164+
165+``Borrowed`` converts a ``UniqueType`` to a ``BorrowedType``. It is
166+defined as follows (along with some additional rules in the
167+typechecker):
168+
169+.. code-block:: idris
170+
171+ data Borrowed : UniqueType -> BorrowedType where
172+ Read : {a : UniqueType} -> a -> Borrowed a
173+
174+ implicit
175+ lend : {a : UniqueType} -> a -> Borrowed a
176+ lend x = Read x
177+
178+A value can be "lent" to another function using ``lend``. Arguments to
179+``lend`` are not counted by the type checker as a reference to a unique
180+value, therefore a value can be lent as many times as desired. Using
181+this, we can write ``showU`` as follows:
182+
183+.. code-block:: idris
184+
185+ showU : Show a => Borrowed (UList a) -> String
186+ showU xs = "[" ++ showU' xs ++ "]" where
187+ showU' : Borrowed (UList a) -> String
188+ showU' [] = ""
189+ showU' [x] = show x
190+ showU' (Read (x :: xs)) = show x ++ ", " ++ showU' (lend xs)
191+
192+Unlike a unique value, a borrowed value may be referred to as many
193+times as desired. However, there is a restriction on how a borrowed
194+value can be used. After all, much like a library book or your
195+neighbour's lawnmower, if a function borrows a value it is expected to
196+return it in exactly the condition in which it was received!
197+
198+The restriction is that when a ``Borrowed`` type is matched, any
199+pattern variables under the ``Read`` which have a unique type may not
200+be referred to at all on the right hand side (unless they are
201+themselves ``lent`` to another function).
202+
203+Uniqueness information is stored in the type, and in particular in
204+function types. Once we're in a unique context, any new function which
205+is constructed will be required to have unique type, which prevents
206+the following sort of bad program being implemented:
207+
208+.. code-block:: idris
209+
210+ foo : UList Int -> IO ()
211+ foo xs = do let f = \x : Int => showU xs
212+ putStrLn $ free xs
213+ putStrLn $ f 42
214+ return ()
215+
216+Since ``lend`` is implicit, in practice for functions to lend and borrow
217+values merely requires the argument to be marked as ``Borrowed``. We can
218+therefore write ``showU`` as follows:
219+
220+.. code-block:: idris
221+
222+ showU : Show a => Borrowed (UList a) -> String
223+ showU xs = "[" ++ showU' xs ++ "]" where
224+ showU' : Borrowed (UList a) -> String
225+ showU' [] = ""
226+ showU' [x] = show x
227+ showU' (x :: xs) = show x ++ ", " ++ showU' xs
228+
229+Problems/Disadvantages/Still to do...
230+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
231+
232+This is a work in progress, there is lots to do. The most obvious
233+problem is the loss of abstraction. On the one hand, we have more
234+precise control over memory usage with ``UniqueType`` and
235+``BorrowedType``, but they are not in general compatible with
236+functions polymorphic over ``Type``. In the short term, we can start
237+to write reactive and low memory systems with this, but longer term it
238+would be nice to support more abstraction.
239+
240+We also haven't checked any of the metatheory, so this could all be
241+fatally flawed! The implementation is based to a large extent on
242+`Uniqueness Typing Simplified
243+<http://lambda-the-ultimate.org/node/2708>`__, by de Vries et al, so
244+there is reason to believe things should be fine, but we still have to
245+do the work.
246+
247+Much as there are with linear types, there are some annoyances when
248+trying to prove properties of functions with unique types (for
249+example, what counts as a use of a value). Since we require *at most*
250+one use of a value, rather than *exactly* one, this seems to be less
251+of an issue in practice, but still needs thought.
docs/tutorial/classes.rstnew file+517
@@ -0,0 +1,517 @@
1+.. _sect-classes:
2+
3+============
4+Type Classes
5+============
6+
7+We often want to define functions which work across several different
8+data types. For example, we would like arithmetic operators to work on
9+``Int``, ``Integer`` and ``Float`` at the very least. We would like
10+``==`` to work on the majority of data types. We would like to be able
11+to display different types in a uniform way.
12+
13+To achieve this, we use a feature which has proved to be effective in
14+Haskell, namely *type classes*. To define a type class, we provide a
15+collection of overloaded operations which describe the interface for
16+*instances* of that class. A simple example is the ``Show`` type
17+class, which is defined in the prelude and provides an interface for
18+converting values to ``String``:
19+
20+.. code-block:: idris
21+
22+ class Show a where
23+ show : a -> String
24+
25+This generates a function of the following type (which we call a
26+*method* of the ``Show`` class):
27+
28+.. code-block:: idris
29+
30+ show : Show a => a -> String
31+
32+We can read this as: “under the constraint that ``a`` is an instance
33+of ``Show``, take an input ``a`` and return a ``String``.” An instance
34+of a class is defined with an ``instance`` declaration, which provides
35+implementations of the function for a specific type. For example, the
36+``Show`` instance for ``Nat`` could be defined as:
37+
38+.. code-block:: idris
39+
40+ instance Show Nat where
41+ show Z = "Z"
42+ show (S k) = "s" ++ show k
43+
44+::
45+
46+ Idris> show (S (S (S Z)))
47+ "sssZ" : String
48+
49+Only one instance of a class can be given for a type — instances may
50+not overlap. Instance declarations can themselves have constraints.
51+To help with resolution, the arguments of an instance must be
52+constructors (either data or type constructors), variables or
53+constants (i.e. you cannot give an instance for a function). For
54+example, to define a ``Show`` instance for vectors, we need to know
55+that there is a ``Show`` instance for the element type, because we are
56+going to use it to convert each element to a ``String``:
57+
58+.. code-block:: idris
59+
60+ instance Show a => Show (Vect n a) where
61+ show xs = "[" ++ show' xs ++ "]" where
62+ show' : Vect n a -> String
63+ show' Nil = ""
64+ show' (x :: Nil) = show x
65+ show' (x :: xs) = show x ++ ", " ++ show' xs
66+
67+Default Definitions
68+-------------------
69+
70+The library defines an ``Eq`` class which provides an interface for
71+comparing values for equality or inequality, with instances for all of
72+the built-in types:
73+
74+.. code-block:: idris
75+
76+ class Eq a where
77+ (==) : a -> a -> Bool
78+ (/=) : a -> a -> Bool
79+
80+To declare an instance of a type, we have to give definitions of all
81+of the methods. For example, for an instance of ``Eq`` for ``Nat``:
82+
83+.. code-block:: idris
84+
85+ instance Eq Nat where
86+ Z == Z = True
87+ (S x) == (S y) = x == y
88+ Z == (S y) = False
89+ (S x) == Z = False
90+
91+ x /= y = not (x == y)
92+
93+It is hard to imagine many cases where the ``/=`` method will be
94+anything other than the negation of the result of applying the ``==``
95+method. It is therefore convenient to give a default definition for
96+each method in the class declaration, in terms of the other method:
97+
98+.. code-block:: idris
99+
100+ class Eq a where
101+ (==) : a -> a -> Bool
102+ (/=) : a -> a -> Bool
103+
104+ x /= y = not (x == y)
105+ x == y = not (x /= y)
106+
107+A minimal complete definition of an ``Eq`` instance requires either
108+``==`` or ``/=`` to be defined, but does not require both. If a method
109+definition is missing, and there is a default definition for it, then
110+the default is used instead.
111+
112+Extending Classes
113+-----------------
114+
115+Classes can also be extended. A logical next step from an equality
116+relation ``Eq`` is to define an ordering relation ``Ord``. We can
117+define an ``Ord`` class which inherits methods from ``Eq`` as well as
118+defining some of its own:
119+
120+.. code-block:: idris
121+
122+ data Ordering = LT | EQ | GT
123+
124+.. code-block:: idris
125+
126+ class Eq a => Ord a where
127+ compare : a -> a -> Ordering
128+
129+ (<) : a -> a -> Bool
130+ (>) : a -> a -> Bool
131+ (<=) : a -> a -> Bool
132+ (>=) : a -> a -> Bool
133+ max : a -> a -> a
134+ min : a -> a -> a
135+
136+The ``Ord`` class allows us to compare two values and determine their
137+ordering. Only the ``compare`` method is required; every other method
138+has a default definition. Using this we can write functions such as
139+``sort``, a function which sorts a list into increasing order,
140+provided that the element type of the list is in the ``Ord`` class. We
141+give the constraints on the type variables left of the fat arrow
142+``=>``, and the function type to the right of the fat arrow:
143+
144+.. code-block:: idris
145+
146+ sort : Ord a => List a -> List a
147+
148+Functions, classes and instances can have multiple
149+constraints. Multiple constaints are written in brackets in a comma
150+separated list, for example:
151+
152+.. code-block:: idris
153+
154+ sortAndShow : (Ord a, Show a) => List a -> String
155+ sortAndShow xs = show (sort xs)
156+
157+Functors and Applicatives
158+-------------------------
159+
160+So far, we have seen single parameter type classes, where the parameter
161+is of type ``Type``. In general, there can be any number (greater than
162+0) of parameters, and the parameters can have *any* type. If the type
163+of the parameter is not ``Type``, we need to give an explicit type
164+declaration. For example, the ``Functor`` class is defined in the
165+library:
166+
167+.. code-block:: idris
168+
169+ class Functor (f : Type -> Type) where
170+ map : (m : a -> b) -> f a -> f b
171+
172+A functor allows a function to be applied across a structure, for
173+example to apply a function to every element in a ``List``:
174+
175+.. code-block:: idris
176+
177+ instance Functor List where
178+ map f [] = []
179+ map f (x::xs) = f x :: map f xs
180+
181+::
182+
183+ Idris> map (*2) [1..10]
184+ [2, 4, 6, 8, 10, 12, 14, 16, 18, 20] : List Integer
185+
186+Having defined ``Functor``, we can define ``Applicative`` which
187+abstracts the notion of function application:
188+
189+.. code-block:: idris
190+
191+ infixl 2 <*>
192+
193+ class Functor f => Applicative (f : Type -> Type) where
194+ pure : a -> f a
195+ (<*>) : f (a -> b) -> f a -> f b
196+
197+Monads and ``do``-notation
198+--------------------------
199+
200+The ``Monad`` class allows us to encapsulate binding and computation,
201+and is the basis of ``do``-notation introduced in Section
202+:ref:`sect-do`. It extends ``Applicative`` as defined above, and is
203+defined as follows:
204+
205+.. code-block:: idris
206+
207+ class Applicative m => Monad (m : Type -> Type) where
208+ (>>=) : m a -> (a -> m b) -> m b
209+
210+Inside a ``do`` block, the following syntactic transformations are
211+applied:
212+
213+- ``x <- v; e`` becomes ``v >>= (\backslashx => e)``
214+
215+- ``v; e`` becomes ``v >>= (\backslash_ => e)``
216+
217+- ``let x = v; e`` becomes ``let x = v in e``
218+
219+``IO`` is an instance of ``Monad``, defined using primitive functions.
220+We can also define an instance for ``Maybe``, as follows:
221+
222+.. code-block:: idris
223+
224+ instance Monad Maybe where
225+ Nothing >>= k = Nothing
226+ (Just x) >>= k = k x
227+
228+Using this we can, for example, define a function which adds two
229+``Maybe Int``, using the monad to encapsulate the error handling:
230+
231+.. code-block:: idris
232+
233+ m_add : Maybe Int -> Maybe Int -> Maybe Int
234+ m_add x y = do x' <- x -- Extract value from x
235+ y' <- y -- Extract value from y
236+ return (x' + y') -- Add them
237+
238+This function will extract the values from ``x`` and ``y``, if they
239+are available, or return ``Nothing`` if they are not. Managing the
240+``Nothing`` cases is achieved by the ``>>=`` operator, hidden by the
241+``do`` notation.
242+
243+::
244+
245+ *classes> m_add (Just 20) (Just 22)
246+ Just 42 : Maybe Int
247+ *classes> m_add (Just 20) Nothing
248+ Nothing : Maybe Int
249+
250+``!``-notation
251+~~~~~~~~~~~~~~
252+
253+In many cases, using ``do``-notation can make programs unnecessarily
254+verbose, particularly in cases such as ``m_add`` above where the value
255+bound is used once, immediately. In these cases, we can use a
256+shorthand version, as follows:
257+
258+.. code-block:: idris
259+
260+ m_add : Maybe Int -> Maybe Int -> Maybe Int
261+ m_add x y = return (!x + !y)
262+
263+The notation ``!expr`` means that the expression ``expr`` should be
264+evaluated and then implicitly bound. Conceptually, we can think of
265+``!`` as being a prefix function with the following type:
266+
267+.. code-block:: idris
268+
269+ (!) : m a -> a
270+
271+Note, however, that it is not really a function, merely syntax! In
272+practice, a subexpression ``!expr`` will lift ``expr`` as high as
273+possible within its current scope, bind it to a fresh name ``x``, and
274+replace ``!expr`` with ``x``. Expressions are lifted depth first, left
275+to right. In practice, ``!``-notation allows us to program in a more
276+direct style, while still giving a notational clue as to which
277+expressions are monadic.
278+
279+For example, the expression:
280+
281+.. code-block:: idris
282+
283+ let y = 42 in f !(g !(print y) !x)
284+
285+is lifted to:
286+
287+.. code-block:: idris
288+
289+ let y = 42 in do y' <- print y
290+ x' <- x
291+ g' <- g y' x'
292+ f g'
293+
294+Monad comprehensions
295+~~~~~~~~~~~~~~~~~~~~
296+
297+The list comprehension notation we saw in Section
298+:ref:`sect-more-expr` is more general, and applies to anything which
299+is an instance of both ``Monad`` and ``Alternative``:
300+
301+.. code-block:: idris
302+
303+ class Applicative f => Alternative (f : Type -> Type) where
304+ empty : f a
305+ (<|>) : f a -> f a -> f a
306+
307+In general, a comprehension takes the form ``[ exp | qual1, qual2, …,
308+qualn ]`` where ``quali`` can be one of:
309+
310+- A generator ``x <- e``
311+
312+- A *guard*, which is an expression of type ``Bool``
313+
314+- A let binding ``let x = e``
315+
316+To translate a comprehension ``[exp | qual1, qual2, …, qualn]``, first
317+any qualifier ``qual`` which is a *guard* is translated to ``guard
318+qual``, using the following function:
319+
320+.. code-block:: idris
321+
322+ guard : Alternative f => Bool -> f ()
323+
324+Then the comprehension is converted to ``do`` notation:
325+
326+.. code-block:: idris
327+
328+ do { qual1; qual2; ...; qualn; return exp; }
329+
330+Using monad comprehensions, an alternative definition for ``m_add``
331+would be:
332+
333+.. code-block:: idris
334+
335+ m_add : Maybe Int -> Maybe Int -> Maybe Int
336+ m_add x y = [ x' + y' | x' <- x, y' <- y ]
337+
338+Idiom brackets
339+--------------
340+
341+While ``do`` notation gives an alternative meaning to sequencing,
342+idioms give an alternative meaning to *application*. The notation and
343+larger example in this section is inspired by Conor McBride and Ross
344+Paterson’s paper “Applicative Programming with Effects” [1]_.
345+
346+First, let us revisit ``m_add`` above. All it is really doing is
347+applying an operator to two values extracted from ``Maybe Int``. We
348+could abstract out the application:
349+
350+.. code-block:: idris
351+
352+ m_app : Maybe (a -> b) -> Maybe a -> Maybe b
353+ m_app (Just f) (Just a) = Just (f a)
354+ m_app _ _ = Nothing
355+
356+Using this, we can write an alternative ``m_add`` which uses this
357+alternative notion of function application, with explicit calls to
358+``m_app``:
359+
360+.. code-block:: idris
361+
362+ m_add' : Maybe Int -> Maybe Int -> Maybe Int
363+ m_add' x y = m_app (m_app (Just (+)) x) y
364+
365+Rather than having to insert ``m_app`` everywhere there is an
366+application, we can use to do the job for us. To do this, we can make
367+``Maybe`` an instance of ``Applicative`` as follows, where ``<>`` is
368+defined in the same way as ``m_app`` above (this is defined in the
369+Idris library):
370+
371+.. code-block:: idris
372+
373+ instance Applicative Maybe where
374+ pure = Just
375+
376+ (Just f) <*> (Just a) = Just (f a)
377+ _ <*> _ = Nothing
378+
379+Using we can use this instance as follows, where a function
380+application ``[| f a1 …an |]`` is translated into ``pure f <> a1 <>
381+…<> an``:
382+
383+.. code-block:: idris
384+
385+ m_add' : Maybe Int -> Maybe Int -> Maybe Int
386+ m_add' x y = [| x + y |]
387+
388+An error-handling interpreter
389+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
390+
391+Idiom notation is commonly useful when defining evaluators. McBride
392+and Paterson describe such an evaluator [1]_, for a language similar
393+to the following:
394+
395+.. code-block:: idris
396+
397+ data Expr = Var String -- variables
398+ | Val Int -- values
399+ | Add Expr Expr -- addition
400+
401+Evaluation will take place relative to a context mapping variables
402+(represented as ``String``s) to integer values, and can possibly fail.
403+We define a data type ``Eval`` to wrap an evaluator:
404+
405+.. code-block:: idris
406+
407+ data Eval : Type -> Type where
408+ MkEval : (List (String, Int) -> Maybe a) -> Eval a
409+
410+Wrapping the evaluator in a data type means we will be able to make it
411+an instance of a type class later. We begin by defining a function to
412+retrieve values from the context during evaluation:
413+
414+.. code-block:: idris
415+
416+ fetch : String -> Eval Int
417+ fetch x = MkEval (\e => fetchVal e) where
418+ fetchVal : List (String, Int) -> Maybe Int
419+ fetchVal [] = Nothing
420+ fetchVal ((v, val) :: xs) = if (x == v)
421+ then (Just val)
422+ else (fetchVal xs)
423+
424+When defining an evaluator for the language, we will be applying
425+functions in the context of an ``Eval``, so it is natural to make
426+``Eval`` an instance of ``Applicative``. Before ``Eval`` can be an
427+instance of ``Applicative`` it is necessary to make ``Eval`` an
428+instance of ``Functor``:
429+
430+.. code-block:: idris
431+
432+ instance Functor Eval where
433+ map f (MkEval g) = MkEval (\e => map f (g e))
434+
435+ instance Applicative Eval where
436+ pure x = MkEval (\e => Just x)
437+
438+ (<*>) (MkEval f) (MkEval g) = MkEval (\x => app (f x) (g x)) where
439+ app : Maybe (a -> b) -> Maybe a -> Maybe b
440+ app (Just fx) (Just gx) = Just (fx gx)
441+ app _ _ = Nothing
442+
443+Evaluating an expression can now make use of the idiomatic application
444+to handle errors:
445+
446+.. code-block:: idris
447+
448+ eval : Expr -> Eval Int
449+ eval (Var x) = fetch x
450+ eval (Val x) = [| x |]
451+ eval (Add x y) = [| eval x + eval y |]
452+
453+ runEval : List (String, Int) -> Expr -> Maybe Int
454+ runEval env e = case eval e of
455+ MkEval envFn => envFn env
456+
457+Named Instances
458+---------------
459+
460+It can be desirable to have multiple instances of a type class, for
461+example to provide alternative methods for sorting or printing values.
462+To achieve this, instances can be *named* as follows:
463+
464+.. code-block:: idris
465+
466+ instance [myord] Ord Nat where
467+ compare Z (S n) = GT
468+ compare (S n) Z = LT
469+ compare Z Z = EQ
470+ compare (S x) (S y) = compare @{myord} x y
471+
472+This declares an instance as normal, but with an explicit name,
473+``myord``. The syntax ``compare @{myord}`` gives an explicit instance to
474+``compare``, otherwise it would use the default instance for ``Nat``. We
475+can use this, for example, to sort a list of ``Nat`` in reverse.
476+Given the following list:
477+
478+.. code-block:: idris
479+
480+ testList : List Nat
481+ testList = [3,4,1]
482+
483+We can sort it using the default ``Ord`` instance, then the named
484+instance ``myord`` as follows, at the Idris prompt:
485+
486+::
487+
488+ *named_instance> show (sort testList)
489+ "[sO, sssO, ssssO]" : String
490+ *named_instance> show (sort @{myord} testList)
491+ "[ssssO, sssO, sO]" : String
492+
493+
494+Determining Parameters
495+----------------------
496+
497+When a class has more than one parameter, it can help resolution if
498+the parameters used to resolve the type class are restricted. For
499+example:
500+
501+.. code-block:: idris
502+
503+ class Monad m => MonadState s (m : Type -> Type) | m where
504+ get : m s
505+ put : s -> m ()
506+
507+In this class, only ``m`` needs to be known to resolve this class, and
508+``s`` can then be determined from the instance. This is declared with
509+the ``| m`` after the class declaration. We call ``m`` a *determining
510+parameter* of the ``MonadState`` class, because it is the parameter
511+used to resolve an instance.
512+
513+
514+.. [1] Conor Mcbride and Ross Paterson. 2008. Applicative programming
515+ with effects. J. Funct. Program. 18, 1 (January 2008),
516+ 1-13. DOI=10.1017/S0956796807006326
517+ http://dx.doi.org/10.1017/S0956796807006326
docs/tutorial/conclusions.rstnew file+54
@@ -0,0 +1,54 @@
1+.. _sect-concs:
2+
3+===============
4+Further Reading
5+===============
6+
7+Further information about Idris programming, and programming with
8+dependent types in general, can be obtained from various sources:
9+
10+- The Idris web site (http://idris-lang.org/) and by asking
11+ questions on the mailing list.
12+
13+- The IRC channel ``#idris``, on
14+ `chat.freenode.net <http://chat.freenode.net>`__.
15+
16+- The wiki (https://github.com/idris-lang/Idris-dev/wiki/) has further
17+ user provided information, in particular:
18+
19+ - https://github.com/idris-lang/Idris-dev/wiki/Manual
20+
21+ - https://github.com/idris-lang/Idris-dev/wiki/Language-Features
22+
23+- Examining the prelude and exploring the ``samples`` in the
24+ distribution. The Idris source can be found online at:
25+ https://github.com/idris-lang/Idris-dev.
26+
27+- Existing projects on the ``Idris Hackers`` web space:
28+ http://idris-hackers.github.io.
29+
30+- Various papers (e.g. [1]_, [2]_, and [3]_). Although these mostly
31+ describe older versions of Idris.
32+
33+.. [1] Edwin Brady and Kevin Hammond. 2012. Resource-Safe systems
34+ programming with embedded domain specific languages. In
35+ Proceedings of the 14th international conference on Practical
36+ Aspects of Declarative Languages (PADL'12), Claudio Russo and
37+ Neng-Fa Zhou (Eds.). Springer-Verlag, Berlin, Heidelberg,
38+ 242-257. DOI=10.1007/978-3-642-27694-1_18
39+ http://dx.doi.org/10.1007/978-3-642-27694-1_18
40+
41+.. [2] Edwin C. Brady. 2011. IDRIS ---: systems programming meets full
42+ dependent types. In Proceedings of the 5th ACM workshop on
43+ Programming languages meets program verification (PLPV
44+ '11). ACM, New York, NY, USA,
45+ 43-54. DOI=10.1145/1929529.1929536
46+ http://doi.acm.org/10.1145/1929529.1929536
47+
48+.. [3] Edwin C. Brady and Kevin Hammond. 2010. Scrapping your
49+ inefficient engine: using partial evaluation to improve
50+ domain-specific language implementation. In Proceedings of the
51+ 15th ACM SIGPLAN international conference on Functional
52+ programming (ICFP '10). ACM, New York, NY, USA,
53+ 297-308. DOI=10.1145/1863543.1863587
54+ http://doi.acm.org/10.1145/1863543.1863587
docs/tutorial/index.rstnew file+34
@@ -0,0 +1,34 @@
1+.. _tutorial-index:
2+
3+####################
4+ The Idris Tutorial
5+####################
6+
7+The is the Idris Tutorial. It will teach you about programming in the Idris Language.
8+
9+.. note::
10+ The documentation for Idris has been published under the Creative
11+ Commons CC0 License. As such to the extent possible under law, *The
12+ Idris Community* has waived all copyright and related or neighboring
13+ rights to Documentation for Idris.
14+
15+ More information concerning the CC0 can be found online at: http://creativecommons.org/publicdomain/zero/1.0/
16+
17+
18+.. toctree::
19+ :maxdepth: 1
20+
21+ introduction
22+ starting
23+ typesfuns
24+ classes
25+ modules
26+ packages
27+ interp
28+ views
29+ theorems
30+ provisional
31+ interactive
32+ syntax
33+ miscellany
34+ conclusions
docs/tutorial/interactive.rstnew file+258
@@ -0,0 +1,258 @@
1+.. _sect-interactive:
2+
3+===================
4+Interactive Editing
5+===================
6+
7+By now, we have seen several examples of how Idris’ dependent type
8+system can give extra confidence in a function’s correctness by giving
9+a more precise description of its intended behaviour in its *type*. We
10+have also seen an example of how the type system can help with EDSL
11+development by allowing a programmer to describe the type system of an
12+object language. However, precise types give us more than verification
13+of programs — we can also exploit types to help write programs which
14+are *correct by construction*.
15+
16+The Idris REPL provides several commands for inspecting and
17+modifying parts of programs, based on their types, such as case
18+splitting on a pattern variable, inspecting the type of a
19+metavariable, and even a basic proof search mechanism. In this
20+section, we explain how these features can be exploited by a text
21+editor, and specifically how to do so in `Vim
22+<https://github.com/idris-hackers/idris-vim>`_. An interactive mode
23+for `Emacs <https://github.com/idris-hackers/idris-emacs>`_ is also
24+available.
25+
26+
27+Editing at the REPL
28+-------------------
29+
30+The REPL provides a number of commands, which we will describe
31+shortly, which generate new program fragments based on the currently
32+loaded module. These take the general form
33+
34+::
35+
36+ :command [line number] [name]
37+
38+That is, each command acts on a specific source line, at a specific
39+name, and outputs a new program fragment. Each command has an
40+alternative form, which *updates* the source file in-place:
41+
42+::
43+
44+ :command! [line number] [name]
45+
46+When the REPL is loaded, it also starts a background process which
47+accepts and responds to REPL commands, using ``idris --client``. For
48+example, if we have a REPL running elsewhere, we can execute commands
49+such as:
50+
51+::
52+
53+ $ idris --client ':t plus'
54+ Prelude.Nat.plus : Nat -> Nat -> Nat
55+ $ idris --client '2+2'
56+ 4 : Integer
57+
58+A text editor can take advantage of this, along with the editing
59+commands, in order to provide interactive editing support.
60+
61+Editing Commands
62+----------------
63+
64+:addclause
65+~~~~~~~~~~
66+
67+The ``:addclause n f`` command (abbreviated ``:ac n f``) creates a
68+template definition for the function named ``f`` declared on line
69+``n``. For example, if the code beginning on line 94 contains:
70+
71+.. code-block:: idris
72+
73+ vzipWith : (a -> b -> c) ->
74+ Vect n a -> Vect n b -> Vect n c
75+
76+then ``:ac 94 vzipWith`` will give:
77+
78+.. code-block:: idris
79+
80+ vzipWith f xs ys = ?vzipWith_rhs
81+
82+The names are chosen according to hints which may be given by a
83+programmer, and then made unique by the machine by adding a digit if
84+necessary. Hints can be given as follows:
85+
86+.. code-block:: idris
87+
88+ %name Vect xs, ys, zs, ws
89+
90+This declares that any names generated for types in the ``Vect`` family
91+should be chosen in the order ``xs``, ``ys``, ``zs``, ``ws``.
92+
93+:casesplit
94+~~~~~~~~~~
95+
96+The ``:casesplit n x`` command, abbreviated ``:cs n x``, splits the
97+pattern variable ``x`` on line ``n`` into the various pattern forms it
98+may take, removing any cases which are impossible due to unification
99+errors. For example, if the code beginning on line 94 is:
100+
101+.. code-block:: idris
102+
103+ vzipWith : (a -> b -> c) ->
104+ Vect n a -> Vect n b -> Vect n c
105+ vzipWith f xs ys = ?vzipWith_rhs
106+
107+then ``:cs 96 xs`` will give:
108+
109+.. code-block:: idris
110+
111+ vzipWith f [] ys = ?vzipWith_rhs_1
112+ vzipWith f (x :: xs) ys = ?vzipWith_rhs_2
113+
114+That is, the pattern variable ``xs`` has been split into the two
115+possible cases ``[]`` and ``x :: xs``. Again, the names are chosen
116+according to the same heuristic. If we update the file (using
117+``:cs!``) then case split on ``ys`` on the same line, we get:
118+
119+.. code-block:: idris
120+
121+ vzipWith f [] [] = ?vzipWith_rhs_3
122+
123+That is, the pattern variable ``ys`` has been split into one case
124+``[]``, Idris having noticed that the other possible case ``y ::
125+ys`` would lead to a unification error.
126+
127+:addmissing
128+~~~~~~~~~~~
129+
130+The ``:addmissing n f`` command, abbreviated ``:am n f``, adds the
131+clauses which are required to make the function ``f`` on line ``n``
132+cover all inputs. For example, if the code beginning on line 94 is
133+
134+.. code-block:: idris
135+
136+ vzipWith : (a -> b -> c) ->
137+ Vect n a -> Vect n b -> Vect n c
138+ vzipWith f [] [] = ?vzipWith_rhs_1
139+
140+then ``:am 96 vzipWith`` gives:
141+
142+.. code-block:: idris
143+
144+ vzipWith f (x :: xs) (y :: ys) = ?vzipWith_rhs_2
145+
146+That is, it notices that there are no cases for non-empty vectors,
147+generates the required clauses, and eliminates the clauses which would
148+lead to unification errors.
149+
150+:proofsearch
151+~~~~~~~~~~~~
152+
153+The ``:proofsearch n f`` command, abbreviated ``:ps n f``, attempts to
154+find a value for the metavariable ``f`` on line ``n`` by proof search,
155+trying values of local variables, recursive calls and constructors of
156+the required family. Optionally, it can take a list of *hints*, which
157+are functions it can try applying to solve the metavariable. For
158+example, if the code beginning on line 94 is:
159+
160+.. code-block:: idris
161+
162+ vzipWith : (a -> b -> c) ->
163+ Vect n a -> Vect n b -> Vect n c
164+ vzipWith f [] [] = ?vzipWith_rhs_1
165+ vzipWith f (x :: xs) (y :: ys) = ?vzipWith_rhs_2
166+
167+then ``:ps 96 vzipWith_rhs_1`` will give
168+
169+.. code-block:: idris
170+
171+ []
172+
173+This works because it is searching for a ``Vect`` of length 0, of
174+which the empty vector is the only possibiliy. Similarly, and perhaps
175+surprisingly, there is only one possibility if we try to solve ``:ps
176+97 vzipWith_rhs_2``:
177+
178+.. code-block:: idris
179+
180+ f x y :: (vzipWith f xs ys)
181+
182+This works because ``vzipWith`` has a precise enough type: The
183+resulting vector has to be non-empty (a ``::``); the first element
184+must have type ``c`` and the only way to get this is to apply ``f`` to
185+``x`` and ``y``; finally, the tail of the vector can only be built
186+recursively.
187+
188+:makewith
189+~~~~~~~~~
190+
191+The ``:makewith n f`` command, abbreviated ``:mw n f``, adds a
192+``with`` to a pattern clause. For example, recall ``parity``. If line
193+10 is:
194+
195+.. code-block:: idris
196+
197+ parity (S k) = ?parity_rhs
198+
199+then ``:mw 10 parity`` will give:
200+
201+.. code-block:: idris
202+
203+ parity (S k) with (_)
204+ parity (S k) | with_pat = ?parity_rhs
205+
206+If we then fill in the placeholder ``_`` with ``parity k`` and case
207+split on ``with_pat`` using ``:cs 11 with_pat`` we get the following
208+patterns:
209+
210+.. code-block:: idris
211+
212+ parity (S (plus n n)) | even = ?parity_rhs_1
213+ parity (S (S (plus n n))) | odd = ?parity_rhs_2
214+
215+Note that case splitting has normalised the patterns here (giving
216+``plus`` rather than ``+``). In any case, we see that using
217+interactive editing significantly simplifies the implementation of
218+dependent pattern matching by showing a programmer exactly what the
219+valid patterns are.
220+
221+Interactive Editing in Vim
222+--------------------------
223+
224+The editor mode for Vim provides syntax highlighting, indentation and
225+interactive editing support using the commands described above.
226+Interactive editing is achieved using the following editor commands,
227+each of which update the buffer directly:
228+
229+- ``\d`` adds a template definition for the name declared on the
230+ current line (using ``:addclause``).
231+
232+- ``\c`` case splits the variable at the cursor (using
233+ ``:casesplit``).
234+
235+- ``\m`` adds the missing cases for the name at the cursor (using
236+ ``:addmissing``).
237+
238+- ``\w`` adds a ``with`` clause (using ``:makewith``).
239+
240+- ``\o`` invokes a proof search to solve the metavariable under the
241+ cursor (using ``:proofsearch``).
242+
243+- ``\p`` invokes a proof search with additional hints to solve the
244+ metavariable under the cursor (using ``:proofsearch``).
245+
246+There are also commands to invoke the type checker and evaluator:
247+
248+- ``\t`` displays the type of the (globally visible) name under the
249+ cursor. In the case of a metavariable, this displays the context
250+ and the expected type.
251+
252+- ``\e`` prompts for an expression to evaluate.
253+
254+- ``\r`` reloads and type checks the buffer.
255+
256+Corresponding commands are also available in the Emacs mode. Support
257+for other editors can be added in a relatively straighforward manner
258+by using ``idris –client``.
docs/tutorial/interp.rstnew file+288
@@ -0,0 +1,288 @@
1+.. _sect-interp:
2+
3+===================================
4+Example: The Well-Typed Interpreter
5+===================================
6+
7+In this section, we’ll use the features we’ve seen so far to write a
8+larger example, an interpreter for a simple functional programming
9+language, with variables, function application, binary operators and
10+an ``if...then...else`` construct. We will use the dependent type
11+system to ensure that any programs which can be represented are
12+well-typed.
13+
14+Representing Languages
15+----------------------
16+
17+First, let us define the types in the language. We have integers,
18+booleans, and functions, represented by ``Ty``:
19+
20+.. code-block:: idris
21+
22+ data Ty = TyInt | TyBool | TyFun Ty Ty
23+
24+We can write a function to translate these representations to a concrete
25+Idris type — remember that types are first class, so can be
26+calculated just like any other value:
27+
28+.. code-block:: idris
29+
30+ interpTy : Ty -> Type
31+ interpTy TyInt = Int
32+ interpTy TyBool = Bool
33+ interpTy (TyFun A T) = interpTy A -> interpTy T
34+
35+We’re going to define a representation of our language in such a way
36+that only well-typed programs can be represented. We’ll index the
37+representations of expressions by their type and the types of local
38+variables (the context), which we’ll be using regularly as an implicit
39+argument, so we define everything in a ``using`` block:
40+
41+.. code-block:: idris
42+
43+ using (G:Vect n Ty)
44+
45+Expressions are indexed by the types of the local variables, and the type of
46+the expression itself:
47+
48+.. code-block:: idris
49+
50+ data Expr : Vect n Ty -> Ty -> Type
51+
52+The full representation of expressions is:
53+
54+.. code-block:: idris
55+
56+ data HasType : (i : Fin n) -> Vect n Ty -> Ty -> Type where
57+ Stop : HasType FZ (t :: G) t
58+ Pop : HasType k G t -> HasType (FS k) (u :: G) t
59+
60+ data Expr : Vect n Ty -> Ty -> Type where
61+ Var : HasType i G t -> Expr G t
62+ Val : (x : Int) -> Expr G TyInt
63+ Lam : Expr (a :: G) t -> Expr G (TyFun a t)
64+ App : Expr G (TyFun a t) -> Expr G a -> Expr G t
65+ Op : (interpTy a -> interpTy b -> interpTy c) ->
66+ Expr G a -> Expr G b -> Expr G c
67+ If : Expr G TyBool ->
68+ Lazy (Expr G a) ->
69+ Lazy (Expr G a) -> Expr G a
70+
71+Since expressions are indexed by their type, we can read the typing
72+rules of the language from the definitions of the constructors. Let us
73+look at each constructor in turn.
74+
75+We use a nameless representation for variables — they are *de Bruijn
76+indexed*. Variables are represented by a proof of their membership in
77+the context, ``HasType i G T``, which is a proof that variable ``i``
78+in context ``G`` has type ``T``. This is defined as follows:
79+
80+.. code-block:: idris
81+
82+ data HasType : (i : Fin n) -> Vect n Ty -> Ty -> Type where
83+ Stop : HasType FZ (t :: G) t
84+ Pop : HasType k G t -> HasType (FS k) (u :: G) t
85+
86+We can treat *Stop* as a proof that the most recently defined variable
87+is well-typed, and *Pop n* as a proof that, if the ``n``\ th most
88+recently defined variable is well-typed, so is the ``n+1``\ th. In
89+practice, this means we use ``Stop`` to refer to the most recently
90+defined variable, ``Pop Stop`` to refer to the next, and so on, via
91+the ``Var`` constructor:
92+
93+.. code-block:: idris
94+
95+ Var : HasType i G t -> Expr G t
96+
97+So, in an expression ``\x,\y. x y``, the variable ``x`` would have a
98+de Bruijn index of 1, represented as ``Pop Stop``, and ``y 0``,
99+represented as ``Stop``. We find these by counting the number of
100+lambdas between the definition and the use.
101+
102+A value carries a concrete representation of an integer:
103+
104+.. code-block:: idris
105+
106+ Val : (x : Int) -> Expr G TyInt
107+
108+A lambda creates a function. In the scope of a function of type ``a ->
109+t``, there is a new local variable of type ``a``, which is expressed
110+by the context index:
111+
112+.. code-block:: idris
113+
114+ Lam : Expr (a :: G) t -> Expr G (TyFun a t)
115+
116+Function application produces a value of type ``t`` given a function
117+from ``a`` to ``t`` and a value of type ``a``:
118+
119+.. code-block:: idris
120+
121+ App : Expr G (TyFun a t) -> Expr G a -> Expr G t
122+
123+We allow arbitrary binary operators, where the type of the operator
124+informs what the types of the arguments must be:
125+
126+.. code-block:: idris
127+
128+ Op : (interpTy a -> interpTy b -> interpTy c) ->
129+ Expr G a -> Expr G b -> Expr G c
130+
131+Finally, if expressions make a choice given a boolean. Each branch
132+must have the same type, and we will evaluate the branches lazily so
133+that only the branch which is taken need be evaluated:
134+
135+.. code-block:: idris
136+
137+ If : Expr G TyBool ->
138+ Lazy (Expr G a) ->
139+ Lazy (Expr G a) ->
140+ Expr G a
141+
142+Writing the Interpreter
143+-----------------------
144+
145+When we evaluate an ``Expr``, we’ll need to know the values in scope,
146+as well as their types. ``Env`` is an environment, indexed over the
147+types in scope. Since an environment is just another form of list,
148+albeit with a strongly specified connection to the vector of local
149+variable types, we use the usual ``::`` and ``Nil`` constructors so
150+that we can use the usual list syntax. Given a proof that a variable
151+is defined in the context, we can then produce a value from the
152+environment:
153+
154+.. code-block:: idris
155+
156+ data Env : Vect n Ty -> Type where
157+ Nil : Env Nil
158+ (::) : interpTy a -> Env G -> Env (a :: G)
159+
160+ lookup : HasType i G t -> Env G -> interpTy t
161+ lookup Stop (x :: xs) = x
162+ lookup (Pop k) (x :: xs) = lookup k xs
163+
164+Given this, an interpreter is a function which
165+translates an ``Expr`` into a concrete Idris value with respect to a
166+specific environment:
167+
168+.. code-block:: idris
169+
170+ interp : Env G -> Expr G t -> interpTy t
171+
172+The complete interpreter is defined as follows, for reference. For
173+each constructor, we translate it into the corresponding Idris value:
174+
175+.. code-block:: idris
176+
177+ interp env (Var i) = lookup i env
178+ interp env (Val x) = x
179+ interp env (Lam sc) = \x => interp (x :: env) sc
180+ interp env (App f s) = interp env f (interp env s)
181+ interp env (Op op x y) = op (interp env x) (interp env y)
182+ interp env (If x t e) = if interp env x then interp env t
183+ else interp env e
184+
185+Let us look at each case in turn. To translate a variable, we simply look it
186+up in the environment:
187+
188+.. code-block:: idris
189+
190+ interp env (Var i) = lookup i env
191+
192+To translate a value, we just return the concrete representation of the
193+value:
194+
195+.. code-block:: idris
196+
197+ interp env (Val x) = x
198+
199+Lambdas are more interesting. In this case, we construct a function
200+which interprets the scope of the lambda with a new value in the
201+environment. So, a function in the object language is translated to an
202+Idris function:
203+
204+.. code-block:: idris
205+
206+ interp env (Lam sc) = \x => interp (x :: env) sc
207+
208+For an application, we interpret the function and its argument and apply
209+it directly. We know that interpreting ``f`` must produce a function,
210+because of its type:
211+
212+.. code-block:: idris
213+
214+ interp env (App f s) = interp env f (interp env s)
215+
216+Operators and interpreters are, again, direct translations into the
217+equivalent Idris constructs. For operators, we apply the function to
218+its operands directly, and for ``If``, we apply the Idris
219+``if...then...else`` construct directly.
220+
221+.. code-block:: idris
222+
223+ interp env (Op op x y) = op (interp env x) (interp env y)
224+ interp env (If x t e) = if interp env x then interp env t
225+ else interp env e
226+
227+Testing
228+-------
229+
230+We can make some simple test functions. Firstly, adding two inputs
231+``\x. \y. y + x`` is written as follows:
232+
233+.. code-block:: idris
234+
235+ add : Expr G (TyFun TyInt (TyFun TyInt TyInt))
236+ add = Lam (Lam (Op (+) (Var Stop) (Var (Pop Stop))))
237+
238+More interestingly, a factorial function ``fact``
239+(e.g. ``\. if (x == 0) then 1 else (fact (x-1) * x)``),
240+can be written as:
241+
242+.. code-block:: idris
243+
244+ fact : Expr G (TyFun TyInt TyInt)
245+ fact = Lam (If (Op (==) (Var Stop) (Val 0))
246+ (Val 1)
247+ (Op (*) (App fact (Op (-) (Var Stop) (Val 1)))
248+ (Var Stop)))
249+
250+Running
251+-------
252+
253+To finish, we write a ``main`` program which interprets the factorial
254+function on user input:
255+
256+.. code-block:: idris
257+
258+ main : IO ()
259+ main = do putStr "Enter a number: "
260+ x <- getLine
261+ print (interp [] fact (cast x))
262+
263+Here, ``cast`` is an overloaded function which converts a value from
264+one type to another if possible. Here, it converts a string to an
265+integer, giving 0 if the input is invalid. An example run of this
266+program at the Idris interactive environment is:
267+
268+
269+.. _factrun:
270+.. literalinclude:: ../listing/idris-prompt-interp.txt
271+
272+
273+Aside: ``cast``
274+~~~~~~~~~~~~~~~
275+
276+The prelude defines a type class ``Cast`` which allows conversion
277+between types:
278+
279+.. code-block:: idris
280+
281+ class Cast from to where
282+ cast : from -> to
283+
284+It is a *multi-parameter* type class, defining the source type and
285+object type of the cast. It must be possible for the type checker to
286+infer *both* parameters at the point where the cast is applied. There
287+are casts defined between all of the primitive types, as far as they
288+make sense.
docs/tutorial/introduction.rstnew file+69
@@ -0,0 +1,69 @@
1+.. _sect-intro:
2+
3+============
4+Introduction
5+============
6+
7+In conventional programming languages, there is a clear distinction
8+between *types* and *values*. For example, in `Haskell
9+<http://www.haskell.org>`_, the following are types, representing
10+integers, characters, lists of characters, and lists of any value
11+respectively:
12+
13+- ``Int``, ``Char``, ``[Char]``, ``[a]``
14+
15+Correspondingly, the following values are examples of inhabitants of
16+those types:
17+
18+- ``42``, ``’a’``, ``Hello world!``, ``[2,3,4,5,6]``
19+
20+In a language with *dependent types*, however, the distinction is less
21+clear. Dependent types allow types to “depend” on values — in other
22+words, types are a *first class* language construct and can be
23+manipulated like any other value. The standard example is the type of
24+lists of a given length [1]_, ``Vect n a``, where ``a`` is the element
25+type and ``n`` is the length of the list and can be an arbitrary term.
26+
27+When types can contain values, and where those values describe
28+properties (e.g. the length of a list) the type of a function can
29+begin to describe its own properties. For example, concatenating two
30+lists has the property that the resulting list’s length is the sum of
31+the lengths of the two input lists. We can therefore give the
32+following type to the ``app`` function, which concatenates vectors:
33+
34+.. code-block:: idris
35+
36+ app : Vect n a -> Vect m a -> Vect (n + m) a
37+
38+This tutorial introduces Idris, a general purpose functional
39+programming language with dependent types. The goal of the Idris
40+project is to build a dependently typed language suitable for
41+verifiable *systems* programming. To this end, Idris is a compiled
42+language which aims to generate efficient executable code. It also has
43+a lightweight foreign function interface which allows easy interaction
44+with external ``C`` libraries.
45+
46+Intended Audience
47+-----------------
48+
49+This tutorial is intended as a brief introduction to the language, and
50+is aimed at readers already familiar with a functional language such
51+as `Haskell <http://www.haskell.org>`_ or `OCaml <http://ocaml.org>`_.
52+In particular, a certain amount of familiarity with Haskell syntax is
53+assumed, although most concepts will at least be explained
54+briefly. The reader is also assumed to have some interest in using
55+dependent types for writing and verifying systems software.
56+
57+Example Code
58+------------
59+
60+This tutorial includes some example code, which has been tested with
61+Idris version . The files are available in the Idris
62+distribution, and provided along side the tutorial source, so that you
63+can try them out easily, under ``tutorial/examples``. However, it is
64+strongly recommended that you can type them in yourself, rather than
65+simply loading and reading them.
66+
67+.. [1]
68+ Typically, and perhaps confusingly, referred to in the dependently
69+ typed programming literature as “vectors”
docs/tutorial/miscellany.rstnew file+546
@@ -0,0 +1,546 @@
1+.. _sect-misc:
2+
3+==========
4+Miscellany
5+==========
6+
7+In this section we discuss a variety of additional features:
8+
9++ auto, implicit, and default arguments;
10++ literate programming;
11++ interfacing with external libraries through the foreign function
12++ interface;
13++ type providers;
14++ code generation; and
15++ the universe hierarchy.
16+
17+Auto implicit arguments
18+-----------------------
19+
20+We have already seen implicit arguments, which allows arguments to be
21+omitted when they can be inferred by the type checker, e.g.
22+
23+.. code-block:: idris
24+
25+ index : {a:Type} -> {n:Nat} -> Fin n -> Vect n a -> a
26+
27+In other situations, it may be possible to infer arguments not by type
28+checking but by searching the context for an appropriate value, or
29+constructing a proof. For example, the following definition of ``head``
30+which requires a proof that the list is non-empty:
31+
32+.. code-block:: idris
33+
34+ isCons : List a -> Bool
35+ isCons [] = False
36+ isCons (x :: xs) = True
37+
38+ head : (xs : List a) -> (isCons xs = True) -> a
39+ head (x :: xs) _ = x
40+
41+If the list is statically known to be non-empty, either because its
42+value is known or because a proof already exists in the context, the
43+proof can be constructed automatically. Auto implicit arguments allow
44+this to happen silently. We define ``head`` as follows:
45+
46+.. code-block:: idris
47+
48+ head : (xs : List a) -> {auto p : isCons xs = True} -> a
49+ head (x :: xs) = x
50+
51+The ``auto`` annotation on the implicit argument means that Idris
52+will attempt to fill in the implicit argument using the ``trivial``
53+tactic, which searches through the context for a proof, and tries to
54+solve with ``refl`` if a proof is not found. Now when ``head`` is
55+applied, the proof can be omitted. In the case that a proof is not
56+found, it can be provided explicitly as normal:
57+
58+.. code-block:: idris
59+
60+ head xs {p = ?headProof}
61+
62+More generally, we can fill in implicit arguments with a default value
63+by annotating them with ``default``. The definition above is equivalent
64+to:
65+
66+.. code-block:: idris
67+
68+ head : (xs : List a) ->
69+ {default proof { trivial; } p : isCons xs = True} -> a
70+ head (x :: xs) = x
71+
72+Implicit conversions
73+--------------------
74+
75+Idris supports the creation of *implicit conversions*, which allow
76+automatic conversion of values from one type to another when required to
77+make a term type correct. This is intended to increase convenience and
78+reduce verbosity. A contrived but simple example is the following:
79+
80+.. code-block:: idris
81+
82+ implicit intString : Int -> String
83+ intString = show
84+
85+ test : Int -> String
86+ test x = "Number " ++ x
87+
88+In general, we cannot append an ``Int`` to a ``String``, but the
89+implicit conversion function ``intString`` can convert ``x`` to a
90+``String``, so the definition of ``test`` is type correct. An implicit
91+conversion is implemented just like any other function, but given the
92+``implicit`` modifier, and restricted to one explicit argument.
93+
94+Only one implicit conversion will be applied at a time. That is,
95+implicit conversions cannot be chained. Implicit conversions of simple
96+types, as above, are however discouraged! More commonly, an implicit
97+conversion would be used to reduce verbosity in an embedded domain
98+specific language, or to hide details of a proof. Such examples are
99+beyond the scope of this tutorial.
100+
101+Literate programming
102+--------------------
103+
104+Like Haskell, Idris supports *literate* programming. If a file has
105+an extension of ``.lidr`` then it is assumed to be a literate file. In
106+literate programs, everything is assumed to be a comment unless the line
107+begins with a greater than sign ``>``, for example:
108+
109+.. code-block:: idris
110+
111+ > module literate
112+
113+ This is a comment. The main program is below
114+
115+ > main : IO ()
116+ > main = putStrLn "Hello literate world!\n"
117+
118+An additional restriction is that there must be a blank line between a
119+program line (beginning with ``>``) and a comment line (beginning with
120+any other character).
121+
122+Foreign function calls
123+----------------------
124+
125+For practical programming, it is often necessary to be able to use
126+external libraries, particularly for interfacing with the operating
127+system, file system, networking, *et cetera*. Idris provides a
128+lightweight foreign function interface for achieving this, as part of
129+the prelude. For this, we assume a certain amount of knowledge of C and
130+the ``gcc`` compiler. First, we define a datatype which describes the
131+external types we can handle:
132+
133+.. code-block:: idris
134+
135+ data FTy = FInt | FFloat | FChar | FString | FPtr | FUnit
136+
137+Each of these corresponds directly to a C type. Respectively: ``int``,
138+``double``, ``char``, ``char*``, ``void*`` and ``void``. There is also a
139+translation to a concrete Idris type, described by the following
140+function:
141+
142+.. code-block:: idris
143+
144+ interpFTy : FTy -> Type
145+ interpFTy FInt = Int
146+ interpFTy FFloat = Float
147+ interpFTy FChar = Char
148+ interpFTy FString = String
149+ interpFTy FPtr = Ptr
150+ interpFTy FUnit = ()
151+
152+A foreign function is described by a list of input types and a return
153+type, which can then be converted to an Idris type:
154+
155+.. code-block:: idris
156+
157+ ForeignTy : (xs:List FTy) -> (t:FTy) -> Type
158+
159+A foreign function is assumed to be impure, so ``ForeignTy`` builds an
160+``IO`` type, for example:
161+
162+.. code-block:: idris
163+
164+ Idris> ForeignTy [FInt, FString] FString
165+ Int -> String -> IO String : Type
166+
167+ Idris> ForeignTy [FInt, FString] FUnit
168+ Int -> String -> IO () : Type
169+
170+We build a call to a foreign function by giving the name of the
171+function, a list of argument types and the return type. The built in
172+construct ``mkForeign`` converts this description to a function callable
173+by Idris:
174+
175+.. code-block:: idris
176+
177+ data Foreign : Type -> Type where
178+ FFun : String -> (xs:List FTy) -> (t:FTy) ->
179+ Foreign (ForeignTy xs t)
180+
181+ mkForeign : Foreign x -> x
182+
183+Note that the compiler expects ``mkForeign`` to be fully applied to
184+build a complete foreign function call. For example, the ``putStr``
185+function is implemented as follows, as a call to an external function
186+``putStr`` defined in the run-time system:
187+
188+.. code-block:: idris
189+
190+ putStr : String -> IO ()
191+ putStr x = mkForeign (FFun "putStr" [FString] FUnit) x
192+
193+Include and linker directives
194+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
195+
196+Foreign function calls are translated directly to calls to C functions,
197+with appropriate conversion between the Idris representation of a
198+value and the C representation. Often this will require extra libraries
199+to be linked in, or extra header and object files. This is made possible
200+through the following directives:
201+
202+- ``%lib target x`` — include the ``libx`` library. If the target is
203+ ``C`` this is equivalent to passing the ``-lx`` option to ``gcc``. If
204+ the target is Java the library will be interpreted as a
205+ ``groupId:artifactId:packaging:version`` dependency coordinate for
206+ maven.
207+
208+- ``%include target x`` — use the header file or import ``x`` for the
209+ given back end target.
210+
211+- ``%link target x.o`` — link with the object file ``x.o`` when using
212+ the given back end target.
213+
214+- ``%dynamic x.so`` — dynamically link the interpreter with the shared
215+ object ``x.so``.
216+
217+Testing foreign function calls
218+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
219+
220+Normally, the Idris interpreter (used for typechecking and at the REPL)
221+will not perform IO actions. Additionally, as it neither generates C
222+code nor compiles to machine code, the ``%lib``, ``%include`` and
223+``%link`` directives have no effect. IO actions and FFI calls can be
224+tested using the special REPL command ``:x EXPR``, and C libraries can
225+be dynamically loaded in the interpreter by using the ``:dynamic``
226+command or the ``%dynamic`` directive. For example:
227+
228+.. code-block:: idris
229+
230+ Idris> :dynamic libm.so
231+ Idris> :x unsafePerformIO ((mkForeign (FFun "sin" [FFloat] FFloat)) 1.6)
232+ 0.9995736030415051 : Float
233+
234+Type Providers
235+--------------
236+
237+Idris type providers, inspired by F#’s type providers, are a means of
238+making our types be “about” something in the world outside of Idris. For
239+example, given a type that represents a database schema and a query that
240+is checked against it, a type provider could read the schema of a real
241+database during type checking.
242+
243+Idris type providers use the ordinary execution semantics of Idris to
244+run an IO action and extract the result. This result is then saved as a
245+constant in the compiled code. It can be a type, in which case it is
246+used like any other type, or it can be a value, in which case it can be
247+used as any other value, including as an index in types.
248+
249+Type providers are still an experimental extension. To enable the
250+extension, use the ``%language`` directive:
251+
252+.. code-block:: idris
253+
254+ %language TypeProviders
255+
256+A provider ``p`` for some type ``t`` is simply an expression of type
257+``IO (Provider t)``. The ``%provide`` directive causes the type checker
258+to execute the action and bind the result to a name. This is perhaps
259+best illustrated with a simple example. The type provider ``fromFile``
260+reads a text file. If the file consists of the string ``Int``, then the
261+type ``Int`` will be provided. Otherwise, it will provide the type
262+``Nat``.
263+
264+.. code-block:: idris
265+
266+ strToType : String -> Type
267+ strToType "Int" = Int
268+ strToType _ = Nat
269+
270+ fromFile : String -> IO (Provider Type)
271+ fromFile fname = do str <- readFile fname
272+ return (Provide (strToType (trim str)))
273+
274+We then use the ``%provide`` directive:
275+
276+.. code-block:: idris
277+
278+ %provide (T1 : Type) with fromFile "theType"
279+
280+ foo : T1
281+ foo = 2
282+
283+If the file named ``theType`` consists of the word ``Int``, then ``foo``
284+will be an ``Int``. Otherwise, it will be a ``Nat``. When Idris
285+encounters the directive, it first checks that the provider expression
286+``fromFile theType`` has type ``IO (Provider Type)``. Next, it executes
287+the provider. If the result is ``Provide t``, then ``T1`` is defined as
288+``t``. Otherwise, the result is an error.
289+
290+Our datatype ``Provider t`` has the following definition:
291+
292+.. code-block:: idris
293+
294+ data Provider a = Error String
295+ | Provide a
296+
297+We have already seen the ``Provide`` constructor. The ``Error``
298+constructor allows type providers to return useful error messages. The
299+example in this section was purposefully simple. More complex type
300+provider implementations, including a statically-checked SQLite binding,
301+are available in an external collection [1]_.
302+
303+C Target
304+--------
305+
306+The default target of Idris is C. Compiling via :
307+
308+::
309+
310+ $ idris hello.idr -o hello
311+
312+is equivalent to :
313+
314+::
315+
316+ $ idris --codegen C hello.idr -o hello
317+
318+When the command above is used, a temporary C source is generated, which
319+is then compiled into an executable named ``hello``.
320+
321+In order to view the generated C code, compile via :
322+
323+::
324+
325+ $ idris hello.idr -S -o hello.c
326+
327+To turn optimisations on, use the ``%flag C`` pragma within the code, as
328+is shown below :
329+
330+.. code-block:: idris
331+
332+ module Main
333+ %flag C "-O3"
334+
335+ factorial : Int -> Int
336+ factorial 0 = 1
337+ factorial n = n * (factorial (n-1))
338+
339+ main : IO ()
340+ main = do
341+ putStrLn $ show $ factorial 3
342+
343+JavaScript Target
344+-----------------
345+
346+Idris is capable of producing *JavaScript* code that can be run in a
347+browser as well as in the *NodeJS* environment or alike. One can use the
348+FFI to communicate with the *JavaScript* ecosystem.
349+
350+Code Generation
351+~~~~~~~~~~~~~~~
352+
353+Code generation is split into two separate targets. To generate code
354+that is tailored for running in the browser issue the following command:
355+
356+::
357+
358+ $ idris --codegen javascript hello.idr -o hello.js
359+
360+The resulting file can be embedded into your HTML just like any other
361+*JavaScript* code.
362+
363+Generating code for *NodeJS* is slightly different. Idris outputs a
364+*JavaScript* file that can be directly executed via ``node``.
365+
366+::
367+
368+ $ idris --codegen node hello.idr -o hello
369+ $ ./hello
370+ Hello world
371+
372+Take into consideration that the *JavaScript* code generator is using
373+``console.log`` to write text to ``stdout``, this means that it will
374+automatically add a newline to the end of each string. This behaviour
375+does not show up in the *NodeJS* code generator.
376+
377+Using the FFI
378+~~~~~~~~~~~~~
379+
380+To write a useful application we need to communicate with the outside
381+world. Maybe we want to manipulate the DOM or send an Ajax request. For
382+this task we can use the FFI. Since most *JavaScript* APIs demand
383+callbacks we need to extend the FFI so we can pass functions as
384+arguments.
385+
386+The *JavaScript* FFI works a little bit differently than the regular
387+FFI. It uses positional arguments to directly insert our arguments into
388+a piece of *JavaScript* code.
389+
390+One could use the primitive addition of *JavaScript* like so:
391+
392+.. code-block:: idris
393+
394+ module Main
395+
396+ primPlus : Int -> Int -> IO Int
397+ primPlus a b = mkForeign (FFun "%0 + %1" [FInt, FInt] FInt) a b
398+
399+ main : IO ()
400+ main = do
401+ a <- primPlus 1 1
402+ b <- primPlus 1 2
403+ print (a, b)
404+
405+Notice that the ``%n`` notation qualifies the position of the ``n``-th
406+argument given to our foreign function starting from 0. When you need a
407+percent sign rather than a position simply use ``%%`` instead.
408+
409+Passing functions to a foreign function is very similar. Let’s assume
410+that we want to call the following function from the *JavaScript* world:
411+
412+.. code-block:: idris
413+
414+ function twice(f, x) {
415+ return f(f(x));
416+ }
417+
418+We obviously need to pass a function ``f`` here (we can infer it from
419+the way we use ``f`` in ``twice``, it would be more obvious if
420+*JavaScript* had types).
421+
422+The *JavaScript* FFI is able to understand functions as arguments when
423+you give it something of type ``FFunction``. The following example code
424+calls ``twice`` in *JavaScript* and returns the result to our Idris
425+program:
426+
427+.. code-block:: idris
428+
429+ module Main
430+
431+ twice : (Int -> Int) -> Int -> IO Int
432+ twice f x = mkForeign (
433+ FFun "twice(%0,%1)" [FFunction FInt FInt, FInt] FInt
434+ ) f x
435+
436+ main : IO ()
437+ main = do
438+ a <- twice (+1) 1
439+ print a
440+
441+The program outputs ``3``, just like we expected.
442+
443+Including external *JavaScript* files
444+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
445+
446+Whenever one is working with *JavaScript* one might want to include
447+external libraries or just some functions that she or he wants to call
448+via FFI which are stored in external files. The *JavaScript* and
449+*NodeJS* code generators understand the ``%include`` directive. Keep in
450+mind that *JavaScript* and *NodeJS* are handled as different code
451+generators, therefore you will have to state which one you want to
452+target. This means that you can include different files for *JavaScript*
453+and *NodeJS* in the same Idris source file.
454+
455+So whenever you want to add an external *JavaScript* file you can do
456+this like so:
457+
458+For *NodeJS*:
459+
460+.. code-block:: idris
461+
462+ %include Node "path/to/external.js"
463+
464+And for use in the browser:
465+
466+.. code-block:: idris
467+
468+ %include JavaScript "path/to/external.js"
469+
470+The given files will be added to the top of the generated code.
471+
472+Including *NodeJS* modules
473+~~~~~~~~~~~~~~~~~~~~~~~~~~
474+
475+The *NodeJS* code generator can also include modules with the ``%lib``
476+directive.
477+
478+.. code-block:: idris
479+
480+ %lib Node "fs"
481+
482+This directive compiles into the following *JavaScript*
483+
484+.. code-block:: javascript
485+
486+ var fs = require("fs");
487+
488+Shrinking down generated *JavaScript*
489+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
490+
491+Idris can produce very big chunks of *JavaScript* code. However, the
492+generated code can be minified using the ``closure-compiler`` from
493+Google. Any other minifier is also suitable but ``closure-compiler``
494+offers advanced compilation that does some aggressive inlining and code
495+elimination. Idris can take full advantage of this compilation mode
496+and it’s highly recommended to use it when shipping a *JavaScript*
497+application written in Idris.
498+
499+Cumulativity
500+------------
501+
502+Since values can appear in types and *vice versa*, it is natural that
503+types themselves have types. For example:
504+
505+::
506+
507+ *universe> :t Nat
508+ Nat : Type
509+ *universe> :t Vect
510+ Vect : Nat -> Type -> Type
511+
512+But what about the type of ``Type``? If we ask Idris it reports
513+
514+::
515+
516+ *universe> :t Type
517+ Type : Type 1
518+
519+If ``Type`` were its own type, it would lead to an inconsistency due to
520+`Girard’s paradox <http://www.cs.cmu.edu/afs/cs.cmu.edu/user/kw/www/scans/girard72thesis.pdf>`_ , so internally there is a
521+*hierarchy* of types (or *universes*):
522+
523+.. code-block:: idris
524+
525+ Type : Type 1 : Type 2 : Type 3 : ...
526+
527+Universes are *cumulative*, that is, if ``x : Type n`` we can also have
528+that ``x : Type m``, as long as ``n < m``. The typechecker generates
529+such universe constraints and reports an error if any inconsistencies
530+are found. Ordinarily, a programmer does not need to worry about this,
531+but it does prevent (contrived) programs such as the following:
532+
533+.. code-block:: idris
534+
535+ myid : (a : Type) -> a -> a
536+ myid _ x = x
537+
538+ idid : (a : Type) -> a -> a
539+ idid = myid _ myid
540+
541+The application of ``myid`` to itself leads to a cycle in the universe
542+hierarchy — ``myid``\ ’s first argument is a ``Type``, which cannot be
543+at a lower level than required if it is applied to itself.
544+
545+.. [1]
546+ https://github.com/david-christiansen/idris-type-providers
docs/tutorial/modules.rstnew file+219
@@ -0,0 +1,219 @@
1+.. _sect-namespaces:
2+
3+=======================
4+Modules and Namespaces
5+=======================
6+
7+An Idris program consists of a collection of modules. Each module
8+includes an optional ``module`` declaration giving the name of the
9+module, a list of ``import`` statements giving the other modules which
10+are to be imported, and a collection of declarations and definitions of
11+types, classes and functions. For example, the listing below gives a
12+module which defines a binary tree type ``BTree`` (in a file
13+``btree.idr``):
14+
15+.. code-block:: idris
16+
17+ module btree
18+
19+ data BTree a = Leaf
20+ | Node (BTree a) a (BTree a)
21+
22+ insert : Ord a => a -> BTree a -> BTree a
23+ insert x Leaf = Node Leaf x Leaf
24+ insert x (Node l v r) = if (x < v) then (Node (insert x l) v r)
25+ else (Node l v (insert x r))
26+
27+ toList : BTree a -> List a
28+ toList Leaf = []
29+ toList (Node l v r) = btree.toList l ++ (v :: btree.toList r)
30+
31+ toTree : Ord a => List a -> BTree a
32+ toTree [] = Leaf
33+ toTree (x :: xs) = insert x (toTree xs)
34+
35+
36+Then, this gives a main program (in a file
37+``bmain.idr``) which uses the ``bst`` module to sort a list:
38+
39+.. code-block:: idris
40+
41+ module Main
42+
43+ import btree
44+
45+ main : IO ()
46+ main = do let t = toTree [1,8,2,7,9,3]
47+ print (btree.toList t)
48+
49+
50+The same names can be defined in multiple modules. This is possible
51+because in practice names are *qualified* with the name of the module.
52+The names defined in the ``btree`` module are, in full:
53+
54++ ``btree.BTree``
55++ ``btree.Leaf``
56++ ``btree.Node``
57++ ``btree.insert``
58++ ``btree.toList``
59++ ``btree.toTree``
60+
61+If names are otherwise unambiguous, there is no need to give the fully
62+qualified name. Names can be disambiguated either by giving an explicit
63+qualification, or according to their type.
64+
65+There is no formal link between the module name and its filename,
66+although it is generally advisable to use the same name for each. An
67+``import`` statement refers to a filename, using dots to separate
68+directories. For example, ``import foo.bar`` would import the file
69+``foo/bar.idr``, which would conventionally have the module declaration
70+``module foo.bar``. The only requirement for module names is that the
71+main module, with the ``main`` function, must be called
72+``Main``—although its filename need not be ``Main.idr``.
73+
74+Export Modifiers
75+----------------
76+
77+By default, all names defined in a module are exported for use by other
78+modules. However, it is good practice only to export a minimal interface
79+and keep internal details abstract. Idris allows functions, types,
80+and classes to be marked as: ``public``, ``abstract`` or ``private``:
81+
82+- ``public`` means that both the name and definition are exported. For
83+ functions, this means that the implementation is exported (which
84+ means, for example, it can be used in a dependent type). For data
85+ types, this means that the type name and the constructors are
86+ exported. For classes, this means that the class name and method
87+ names are exported.
88+
89+- ``abstract`` means that only the name is exported. For functions,
90+ this means that the implementation is not exported. For data types,
91+ this means that the type name is exported but not the constructors.
92+ For classes, this means that the class name is exported but not the
93+ method names.
94+
95+- ``private`` means that neither the name nor the definition is
96+ exported.
97+
98+.. note::
99+ If any definition is given an export modifier, then all names with no modifier are assumed to be ``private``.
100+
101+For our ``btree`` module, it makes sense for the tree data type and the
102+functions to be exported as ``abstract``, as we see below:
103+
104+.. code-block:: idris
105+
106+ module btree
107+
108+ abstract data BTree a = Leaf
109+ | Node (BTree a) a (BTree a)
110+
111+ abstract
112+ insert : Ord a => a -> BTree a -> BTree a
113+ insert x Leaf = Node Leaf x Leaf
114+ insert x (Node l v r) = if (x < v) then (Node (insert x l) v r)
115+ else (Node l v (insert x r))
116+
117+ abstract
118+ toList : BTree a -> List a
119+ toList Leaf = []
120+ toList (Node l v r) = btree.toList l ++ (v :: btree.toList r)
121+
122+ abstract
123+ toTree : Ord a => List a -> BTree a
124+ toTree [] = Leaf
125+ toTree (x :: xs) = insert x (toTree xs)
126+
127+Finally, the default export mode can be changed with the ``%access``
128+directive, for example:
129+
130+In this case, any function with no access modifier will be exported as
131+``abstract``, rather than left ``private``.
132+
133+Additionally, a module can re-export a module it has imported, by using
134+the ``public`` modifier on an ``import``. For example:
135+
136+.. code-block:: idris
137+
138+ module A
139+
140+ import B import public C
141+
142+ public a : AType a = ...
143+
144+The module ``A`` will export the name ``a``, as well as any public or
145+abstract names in module ``C``, but will not re-export anything from
146+module ``B``.
147+
148+Explicit Namespaces
149+-------------------
150+
151+Defining a module also defines a namespace implicitly. However,
152+namespaces can also be given *explicitly*. This is most useful if you
153+wish to overload names within the same module:
154+
155+.. code-block:: idris
156+
157+ module foo
158+
159+ namespace x
160+ test : Int -> Int
161+ test x = x * 2
162+
163+ namespace y
164+ test : String -> String
165+ test x = x ++ x
166+
167+This (admittedly contrived) module defines two functions with fully
168+qualified names ``foo.x.test`` and ``foo.y.test``, which can be
169+disambiguated by their types:
170+
171+::
172+
173+ *foo> test 3
174+ 6 : Int
175+ *foo> test "foo"
176+ "foofoo" : String
177+
178+Parameterised blocks
179+--------------------
180+
181+Groups of functions can be parameterised over a number of arguments
182+using a ``parameters`` declaration, for example:
183+
184+.. code-block:: idris
185+
186+ parameters (x : Nat, y : Nat)
187+ addAll : Nat -> Nat
188+ addAll z = x + y + z
189+
190+The effect of a ``parameters`` block is to add the declared parameters
191+to every function, type and data constructor within the block. Outside
192+the block, the parameters must be given explicitly:
193+
194+::
195+
196+ *params> :t addAll
197+ addAll : Nat -> Nat -> Nat -> Nat
198+
199+Parameters blocks can be nested, and can also include data declarations,
200+in which case the parameters are added explicitly to all type and data
201+constructors. They may also be dependent types with implicit arguments:
202+
203+.. code-block:: idris
204+
205+ parameters (y : Nat, xs : Vect x a)
206+ data Vects : Type -> Type where
207+ MkVects : Vect y a -> Vects a
208+
209+ append : Vects a -> Vect (x + y) a
210+ append (MkVects ys) = xs ++ ys
211+
212+To use ``Vects`` or ``append`` outside the block, we must also give the
213+``xs`` and ``y`` arguments. Here, we can use placeholders for the values
214+which can be inferred by the type checker:
215+
216+::
217+
218+ *params> show (append _ _ (MkVects _ [1,2,3] [4,5,6]))
219+ "[1, 2, 3, 4, 5, 6]" : String
docs/tutorial/packages.rstnew file+77
@@ -0,0 +1,77 @@
1+.. _sect-packages:
2+
3+========
4+Packages
5+========
6+
7+Idris includes a simple system for building packages from a
8+package description file. These files can be used with the Idris
9+compiler to manage the development process of your Idris
10+programmes and packages.
11+
12+Package Descriptions
13+--------------------
14+
15+A package description includes the following:
16+
17++ A header, consisting of the keyword package followed by the package name.
18++ Fields describing package contents, ``<field> = <value>``
19+
20+At least one field must be the modules field, where the value is a
21+comma separated list of modules. For example, a library test which
22+has two modules ``foo.idr`` and ``bar.idr`` as source files would be
23+written as follows::
24+
25+ package foo
26+
27+ modules = foo, bar
28+
29+Other examples of package files can be found in the ``libs`` directory
30+of the main Idris repository, and in `third-party libraries <https://github.com/idris-lang/Idris-dev/wiki/Libraries>`_.
31+
32+Other common fields which may be present in an ``ipkg`` file are:
33+
34++ ``sourcedir = <dir>``, which gives the directory (relative to the
35+ current directory) which contains the source. Default is the current
36+ directory.
37+
38++ ``executable = <output>``, which gives the name of the executable
39+ file to generate.
40+
41++ ``main = <module>``, which gives the name of the main module, and
42+ must be present if the executable field is present.
43+
44++ ``opts = "<idris options>"``, which allows options (such as other
45+ packages) to be passed to Idris.
46+
47+In more advanced cases, particularly to support creating bindings to
48+external ``C`` libraries, the following options are available:
49+
50++ ``makefile = <file>``, which specifies a ``Makefile``, to be built
51+ before the Idris modules, for example to support linking with a
52+ ``C`` library.
53+
54++ ``libs = <libs>``, which gives a comma separated list of libraries
55+ which must be present for the package to be usable.
56+
57++ ``objs = <objs>``, which gives a comma separated list of additional
58+ object files to be installed, perhaps generated by the ``Makefile``.
59+
60+Using Package files
61+-------------------
62+
63+Given an Idris package file ``text.ipkg`` it can be used with the Idris compiler as follows:
64+
65++ ``idris --build test.ipkg`` will build all modules in the package
66+
67++ ``idris --install test.ipkg`` will install the package, making it
68+ accessible by other Idris libraries and programs.
69+
70++ ``idris --clean test.ipkg`` will delete all intermediate code and
71+ executable files generated when building.
72+
73+Once the test package has been installed, the command line option
74+``--package test`` makes it accessible (abbreviated to ``-p test``).
75+For example::
76+
77+ idris -p test Main.idr
docs/tutorial/provisional.rstnew file+268
@@ -0,0 +1,268 @@
1+.. _sect-provisional:
2+
3+=======================
4+Provisional Definitions
5+=======================
6+
7+Sometimes when programming with dependent types, the type required by
8+the type checker and the type of the program we have written will be
9+different (in that they do not have the same normal form), but
10+nevertheless provably equal. For example, recall the ``parity``
11+function:
12+
13+.. code-block:: idris
14+
15+ data Parity : Nat -> Type where
16+ Even : Parity (n + n)
17+ Odd : Parity (S (n + n))
18+
19+We’d like to implement this as follows:
20+
21+.. code-block:: idris
22+
23+ parity : (n:Nat) -> Parity n
24+ parity Z = Even {n=Z}
25+ parity (S Z) = Odd {n=Z}
26+ parity (S (S k)) with (parity k)
27+ parity (S (S (j + j))) | Even = Even {n=S j}
28+ parity (S (S (S (j + j)))) | Odd = Odd {n=S j}
29+
30+This simply states that zero is even, one is odd, and recursively, the
31+parity of ``k+2`` is the same as the parity of ``k``. Explicitly marking
32+the value of ``n`` is even and odd is necessary to help type inference.
33+Unfortunately, the type checker rejects this:
34+
35+::
36+
37+ viewsbroken.idr:12:10:When elaborating right hand side of ViewsBroken.parity:
38+ Can't unify
39+ Parity (plus (S j) (S j))
40+ with
41+ Parity (S (S (plus j j)))
42+
43+ Specifically:
44+ Can't unify
45+ plus (S j) (S j)
46+ with
47+ S (S (plus j j))
48+
49+The type checker is telling us that ``(j+1)+(j+1)`` and ``2+j+j`` do not
50+normalise to the same value. This is because ``plus`` is defined by
51+recursion on its first argument, and in the second value, there is a
52+successor symbol on the second argument, so this will not help with
53+reduction. These values are obviously equal — how can we rewrite the
54+program to fix this problem?
55+
56+Provisional definitions
57+-----------------------
58+
59+*Provisional definitions* help with this problem by allowing us to defer
60+the proof details until a later point. There are two main reasons why
61+they are useful.
62+
63+- When *prototyping*, it is useful to be able to test programs before
64+ finishing all the details of proofs.
65+
66+- When *reading* a program, it is often much clearer to defer the proof
67+ details so that they do not distract the reader from the underlying
68+ algorithm.
69+
70+Provisional definitions are written in the same way as ordinary
71+definitions, except that they introduce the right hand side with a
72+``?=`` rather than ``=``. We define ``parity`` as follows:
73+
74+When written in this form, instead of reporting a type error, Idris
75+will insert a metavariable standing for a theorem which will correct the
76+type error. Idris tells us we have two proof obligations, with names
77+generated from the module and function names:
78+
79+.. code-block:: idris
80+
81+ *views> :m
82+ Global metavariables:
83+ [views.parity_lemma_2,views.parity_lemma_1]
84+
85+The first of these has the following type:
86+
87+.. code-block:: idris
88+
89+ *views> :p views.parity_lemma_1
90+
91+ ---------------------------------- (views.parity_lemma_1) --------
92+ {hole0} : (j : Nat) -> (Parity (plus (S j) (S j))) -> Parity (S (S (plus j j)))
93+
94+ -views.parity_lemma_1>
95+
96+The two arguments are ``j``, the variable in scope from the pattern
97+match, and ``value``, which is the value we gave in the right hand side
98+of the provisional definition. Our goal is to rewrite the type so that
99+we can use this value. We can achieve this using the following theorem
100+from the prelude:
101+
102+.. code-block:: idris
103+
104+ plusSuccRightSucc : (left : Nat) -> (right : Nat) ->
105+ S (left + right) = left + (S right)
106+
107+We need to use ``compute`` again to unfold the definition of ``plus``:
108+
109+.. code-block:: idris
110+
111+ -views.parity_lemma_1> compute
112+
113+
114+ ---------------------------------- (views.parity_lemma_1) --------
115+ {hole0} : (j : Nat) -> (Parity (S (plus j (S j)))) -> Parity (S (S (plus j j)))
116+
117+After applying ``intros`` we have:
118+
119+.. code-block:: idris
120+
121+ -views.parity_lemma_1> intros
122+
123+ j : Nat
124+ value : Parity (S (plus j (S j)))
125+ ---------------------------------- (views.parity_lemma_1) --------
126+ {hole2} : Parity (S (S (plus j j)))
127+
128+Then we apply the ``plusSuccRightSucc`` rewrite rule, symmetrically, to
129+``j`` and ``j``, giving:
130+
131+.. code-block:: idris
132+
133+ -views.parity_lemma_1> rewrite sym (plusSuccRightSucc j j)
134+
135+ j : Nat
136+ value : Parity (S (plus j (S j)))
137+ ---------------------------------- (views.parity_lemma_1) --------
138+ {hole3} : Parity (S (plus j (S j)))
139+
140+``sym`` is a function, defined in the library, which reverses the order
141+of the rewrite:
142+
143+.. code-block:: idris
144+
145+ sym : l = r -> r = l
146+ sym Refl = Refl
147+
148+We can complete this proof using the ``trivial`` tactic, which finds
149+``value`` in the premises. The proof of the second lemma proceeds in
150+exactly the same way.
151+
152+We can now test the ``natToBin`` function from Section :ref:`sect-nattobin`
153+at the prompt. The number 42 is 101010 in binary. The binary digits are
154+reversed:
155+
156+.. code-block:: idris
157+
158+ *views> show (natToBin 42)
159+ "[False, True, False, True, False, True]" : String
160+
161+Suspension of Disbelief
162+-----------------------
163+
164+Idris requires that proofs be complete before compiling programs
165+(although evaluation at the prompt is possible without proof details).
166+Sometimes, especially when prototyping, it is easier not to have to do
167+this. It might even be beneficial to test programs before attempting to
168+prove things about them — if testing finds an error, you know you had
169+better not waste your time proving something!
170+
171+Therefore, Idris provides a built-in coercion function, which allows
172+you to use a value of the incorrect types:
173+
174+.. code-block:: idris
175+
176+ believe_me : a -> b
177+
178+Obviously, this should be used with extreme caution. It is useful when
179+prototyping, and can also be appropriate when asserting properties of
180+external code (perhaps in an external C library). The “proof” of
181+``views.parity_lemma_1`` using this is:
182+
183+.. code-block:: idris
184+
185+ views.parity_lemma_2 = proof {
186+ intro;
187+ intro;
188+ exact believe_me value;
189+ }
190+
191+The ``exact`` tactic allows us to provide an exact value for the proof.
192+In this case, we assert that the value we gave was correct.
193+
194+Example: Binary numbers
195+-----------------------
196+
197+Previously, we implemented conversion to binary numbers using the
198+``Parity`` view. Here, we show how to use the same view to implement a
199+verified conversion to binary. We begin by indexing binary numbers over
200+their ``Nat`` equivalent. This is a common pattern, linking a
201+representation (in this case ``Binary``) with a meaning (in this case
202+``Nat``):
203+
204+.. code-block:: idris
205+
206+ data Binary : Nat -> Type where
207+ bEnd : Binary Z
208+ bO : Binary n -> Binary (n + n)
209+ bI : Binary n -> Binary (S (n + n))
210+
211+``bO`` and ``bI`` take a binary number as an argument and effectively
212+shift it one bit left, adding either a zero or one as the new least
213+significant bit. The index, ``n + n`` or ``S (n + n)`` states the result
214+that this left shift then add will have to the meaning of the number.
215+This will result in a representation with the least significant bit at
216+the front.
217+
218+Now a function which converts a Nat to binary will state, in the type,
219+that the resulting binary number is a faithful representation of the
220+original Nat:
221+
222+.. code-block:: idris
223+
224+ natToBin : (n:Nat) -> Binary n
225+
226+The ``Parity`` view makes the definition fairly simple — halving the
227+number is effectively a right shift after all — although we need to use
228+a provisional definition in the odd case:
229+
230+.. code-block:: idris
231+
232+ natToBin : (n:Nat) -> Binary n
233+ natToBin Z = bEnd
234+ natToBin (S k) with (parity k)
235+ natToBin (S (j + j)) | even = bI (natToBin j)
236+ natToBin (S (S (j + j))) | odd ?= bO (natToBin (S j))
237+
238+The problem with the odd case is the same as in the definition of
239+``parity``, and the proof proceeds in the same way:
240+
241+.. code-block:: idris
242+
243+ natToBin_lemma_1 = proof {
244+ intro;
245+ intro;
246+ rewrite sym (plusSuccRightSucc j j);
247+ trivial;
248+ }
249+
250+To finish, we’ll implement a main program which reads an integer from
251+the user and outputs it in binary.
252+
253+.. code-block:: idris
254+
255+ main : IO ()
256+ main = do putStr "Enter a number: "
257+ x <- getLine
258+ print (natToBin (fromInteger (cast x)))
259+
260+For this to work, of course, we need a ``Show`` instance for
261+``Binary n``:
262+
263+.. code-block:: idris
264+
265+ instance Show (Binary n) where
266+ show (bO x) = show x ++ "0"
267+ show (bI x) = show x ++ "1"
268+ show bEnd = ""
docs/tutorial/starting.rstnew file+90
@@ -0,0 +1,90 @@
1+.. _sect-starting:
2+
3+===============
4+Getting Started
5+===============
6+
7+Prerequisites
8+-------------
9+
10+Before installing Idris, you will need to make sure you have all
11+of the necessary libraries and tools. You will need:
12+
13+- A fairly recent Haskell platform. Version 2013.2.0.0 should be
14+ sufficiently recent, though it is better to be completely up to
15+ date.
16+
17+- The *GNU Multiple Precision Arithmetic Library* (GMP) is available
18+ from MacPorts/Homebrew and all major Linux distributions.
19+
20+Downloading and Installing
21+--------------------------
22+
23+The easiest way to install Idris, if you have all of the
24+prerequisites, is to type:
25+
26+::
27+
28+ cabal update; cabal install idris
29+
30+This will install the latest version released on Hackage, along with
31+any dependencies. If, however, you would like the most up to date
32+development version you can find it, as well as build intructions, on
33+GitHub at: https://github.com/idris-lang/Idris-dev.
34+
35+To check that installation has succeeded, and to write your first
36+Idris program, create a file called “``hello.idr``” containing the
37+following text:
38+
39+.. code-block:: idris
40+
41+ module Main
42+
43+ main : IO ()
44+ main = putStrLn "Hello world"
45+
46+If you are familiar with Haskell, it should be fairly clear what the
47+program is doing and how it works, but if not, we will explain the
48+details later. You can compile the program to an executable by
49+entering ``idris hello.idr -o hello`` at the shell prompt. This will
50+create an executable called ``hello``, which you can run:
51+
52+::
53+
54+ $ idris hello.idr -o hello
55+ $ ./hello
56+ Hello world
57+
58+Note that the ``$`` indicates the shell prompt! Should the Idris
59+executable not be found please ensure that you have added
60+``~/.cabal/bin`` to your ``$PATH`` environment variable. Mac OS X
61+users may find they need to use ``~/Library/Haskell/bin``
62+instead. Some useful options to the Idris command are:
63+
64+- ``-o prog`` to compile to an executable called ``prog``.
65+
66+- ``--check`` type check the file and its dependencies without
67+ starting the interactive environment.
68+
69+- ``--help`` display usage summary and command line options
70+
71+The Interactive Environment
72+---------------------------
73+
74+Entering ``idris`` at the shell prompt starts up the interactive
75+environment. You should see something like the following:
76+
77+.. literalinclude:: ../listing/idris-prompt-start.txt
78+
79+This gives a ``ghci`` style interface which allows evaluation of, as
80+well as type checking of, expressions; theorem proving, compilation;
81+editing; and various other operations. The command ``:?`` gives a list
82+of supported commands. Below, we see an example run in
83+which ``hello.idr`` is loaded, the type of ``main`` is checked and
84+then the program is compiled to the executable ``hello``. Type
85+checking a file, if successful, creates a bytecode version of the file
86+(in this case ``hello.ibc``) to speed up loading in future. The
87+bytecode is regenerated if the source file changes.
88+
89+.. _run1:
90+.. literalinclude:: ../listing/idris-prompt-helloworld.txt
docs/tutorial/syntax.rstnew file+208
@@ -0,0 +1,208 @@
1+Syntax Extensions
2+=================
3+
4+supports the implementation of *Embedded Domain Specific Languages*
5+(EDSLs) in several ways [1]_. One way, as we have already seen, is
6+through extending ``do`` notation. Another important way is to allow
7+extension of the core syntax. In this section we describe two ways of
8+extending the syntax: ``syntax`` rules and ``dsl`` notation.
9+
10+``syntax`` rules
11+----------------
12+
13+We have seen ``if...then...else`` expressions, but these are not built
14+in. Instead, we can define a function in the prelude as follows (we
15+have already seen this function in Section :ref:`sect-lazy`):
16+
17+.. code-block:: idris
18+
19+ boolCase : (x:Bool) -> Lazy a -> Lazy a -> a;
20+ boolCase True t e = t;
21+ boolCase False t e = e;
22+
23+and then extend the core syntax with a ``syntax`` declaration:
24+
25+.. code-block:: idris
26+
27+ syntax "if" [test] "then" [t] "else" [e] = boolCase test t e;
28+
29+The left hand side of a ``syntax`` declaration describes the syntax
30+rule, and the right hand side describes its expansion. The syntax rule
31+itself consists of:
32+
33+- **Keywords** — here, ``if``, ``then`` and ``else``, which must be
34+ valid identifiers
35+
36+- **Non-terminals** — included in square brackets, ``[test]``, ``[t]``
37+ and ``[e]`` here, which stand for arbitrary expressions. To avoid
38+ parsing ambiguities, these expressions cannot use syntax extensions
39+ at the top level (though they can be used in parentheses).
40+
41+- **Names** — included in braces, which stand for names which may be
42+ bound on the right hand side.
43+
44+- **Symbols** — included in quotations marks, e.g. ``:=``. This can
45+ also be used to include reserved words in syntax rules, such as
46+ ``let`` or ``in``.
47+
48+The limitations on the form of a syntax rule are that it must include
49+at least one symbol or keyword, and there must be no repeated
50+variables standing for non-terminals. Any expression can be used, but
51+if there are two non-terminals in a row in a rule, only simple
52+expressions may be used (that is, variables, constants, or bracketed
53+expressions). Rules can use previously defined rules, but may not be
54+recursive. The following syntax extensions would therefore be valid:
55+
56+.. code-block:: idris
57+
58+ syntax [var] ":=" [val] = Assign var val;
59+ syntax [test] "?" [t] ":" [e] = if test then t else e;
60+ syntax "select" [x] "from" [t] "where" [w] = SelectWhere x t w;
61+ syntax "select" [x] "from" [t] = Select x t;
62+
63+Syntax macros can be further restricted to apply only in patterns (i.e.,
64+only on the left hand side of a pattern match clause) or only in terms
65+(i.e. everywhere but the left hand side of a pattern match clause) by
66+being marked as ``pattern`` or ``term`` syntax rules. For example, we
67+might define an interval as follows, with a static check that the lower
68+bound is below the upper bound using ``so``:
69+
70+.. code-block:: idris
71+
72+ data Interval : Type where
73+ MkInterval : (lower : Float) -> (upper : Float) ->
74+ so (lower < upper) -> Interval
75+
76+We can define a syntax which, in patterns, always matches ``oh`` for
77+the proof argument, and in terms requires a proof term to be provided:
78+
79+.. code-block:: idris
80+
81+ pattern syntax "[" [x] "..." [y] "]" = MkInterval x y oh
82+ term syntax "[" [x] "..." [y] "]" = MkInterval x y ?bounds_lemma
83+
84+In terms, the syntax ``[x...y]`` will generate a proof obligation
85+``bounds_lemma`` (possibly renamed).
86+
87+Finally, syntax rules may be used to introduce alternative binding
88+forms. For example, a ``for`` loop binds a variable on each iteration:
89+
90+.. code-block:: idris
91+
92+ syntax "for" {x} "in" [xs] ":" [body] = forLoop xs (\x => body)
93+
94+ main : IO ()
95+ main = do for x in [1..10]:
96+ putStrLn ("Number " ++ show x)
97+ putStrLn "Done!"
98+
99+Note that we have used the ``{x}`` form to state that ``x`` represents
100+a bound variable, substituted on the right hand side. We have also put
101+``in`` in quotation marks since it is already a reserved word.
102+
103+``dsl`` notation
104+----------------
105+
106+The well-typed interpreter in Section :ref:`sect-interp` is a simple
107+example of a common programming pattern with dependent types. Namely:
108+describe an *object language* and its type system with dependent types
109+to guarantee that only well-typed programs can be represented, then
110+program using that representation. Using this approach we can, for
111+example, write programs for serialising binary data [2]_ or running
112+concurrent processes safely [3]_.
113+
114+Unfortunately, the form of object language programs makes it rather
115+hard to program this way in practice. Recall the factorial program in
116+``Expr`` for example:
117+
118+.. code-block:: idris
119+
120+ fact : Expr G (TyFun TyInt TyInt)
121+ fact = Lam (If (Op (==) (Var Stop) (Val 0))
122+ (Val 1) (Op (*) (app fact (Op (-) (Var Stop) (Val 1)))
123+ (Var Stop)))
124+
125+Since this is a particularly useful pattern, Idris provides syntax
126+overloading [1]_ to make it easier to program in such object
127+languages:
128+
129+.. code-block:: idris
130+
131+ mkLam : TTName -> Expr (t::g) t' -> Expr g (TyFun t t')
132+ mkLam _ body = Lam body
133+
134+ dsl expr
135+ variable = Var
136+ index_first = Stop
137+ index_next = Pop
138+ lambda = mkLam
139+
140+A ``dsl`` block describes how each syntactic construct is represented
141+in an object language. Here, in the ``expr`` language, any variable is
142+translated to the ``Var`` constructor, using ``Pop`` and ``Stop`` to
143+construct the de Bruijn index (i.e., to count how many bindings since
144+the variable itself was bound); and any lambda is translated to a
145+``Lam`` constructor. The ``mkLam`` function simply ignores its first
146+argument, which is the name that the user chose for the variable. It
147+is also possible to overload ``let`` and dependent function syntax
148+(``pi``) in this way. We can now write ``fact`` as follows:
149+
150+.. code-block:: idris
151+
152+ fact : Expr G (TyFun TyInt TyInt)
153+ fact = expr (\x => If (Op (==) x (Val 0))
154+ (Val 1) (Op (*) (app fact (Op (-) x (Val 1))) x))
155+
156+In this new version, ``expr`` declares that the next expression will
157+be overloaded. We can take this further, using idiom brackets, by
158+declaring:
159+
160+.. code-block:: idris
161+
162+ (<$>) : (f : Lazy (Expr G (TyFun a t))) -> Expr G a -> Expr G t
163+ (<$>) f a = App f a
164+
165+ pure : Expr G a -> Expr G a
166+ pure = id
167+
168+Note that there is no need for these to be part of an instance of
169+``Applicative``, since idiom bracket notation translates directly to
170+the names ``<*>`` and ``pure``, and ad-hoc type-directed overloading
171+is allowed. We can now say:
172+
173+.. code-block:: idris
174+
175+ fact : Expr G (TyFun TyInt TyInt)
176+ fact = expr (\x => If (Op (==) x (Val 0))
177+ (Val 1) (Op (*) [| fact (Op (-) x (Val 1)) |] x))
178+
179+With some more ad-hoc overloading and type class instances, and a new
180+syntax rule, we can even go as far as:
181+
182+.. code-block:: idris
183+
184+ syntax "IF" [x] "THEN" [t] "ELSE" [e] = If x t e
185+
186+ fact : Expr G (TyFun TyInt TyInt)
187+ fact = expr (\x => IF x == 0 THEN 1 ELSE [| fact (x - 1) |] * x)
188+
189+
190+.. [1] Edwin Brady and Kevin Hammond. 2012. Resource-Safe systems
191+ programming with embedded domain specific languages. In
192+ Proceedings of the 14th international conference on Practical
193+ Aspects of Declarative Languages (PADL'12), Claudio Russo and
194+ Neng-Fa Zhou (Eds.). Springer-Verlag, Berlin, Heidelberg,
195+ 242-257. DOI=10.1007/978-3-642-27694-1_18
196+ http://dx.doi.org/10.1007/978-3-642-27694-1_18
197+
198+.. [2] Edwin C. Brady. 2011. IDRIS ---: systems programming meets full
199+ dependent types. In Proceedings of the 5th ACM workshop on
200+ Programming languages meets program verification (PLPV
201+ '11). ACM, New York, NY, USA,
202+ 43-54. DOI=10.1145/1929529.1929536
203+ http://doi.acm.org/10.1145/1929529.1929536
204+
205+.. [3] Edwin Brady and Kevin Hammond. 2010. Correct-by-Construction
206+ Concurrency: Using Dependent Types to Verify Implementations of
207+ Effectful Resource Usage Protocols. Fundam. Inf. 102, 2 (April
208+ 2010), 145-176. http://dl.acm.org/citation.cfm?id=1883636
docs/tutorial/theorems.rstnew file+447
@@ -0,0 +1,447 @@
1+.. _sect-theorems:
2+
3+===============
4+Theorem Proving
5+===============
6+
7+Equality
8+--------
9+
10+Idris allows propositional equalities to be declared, allowing theorems about
11+programs to be stated and proved. Equality is built in, but conceptually
12+has the following definition:
13+
14+.. code-block:: idris
15+
16+ data (=) : a -> b -> Type where
17+ Refl : x = x
18+
19+Equalities can be proposed between any values of any types, but the only
20+way to construct a proof of equality is if values actually are equal.
21+For example:
22+
23+.. code-block:: idris
24+
25+ fiveIsFive : 5 = 5
26+ fiveIsFive = Refl
27+
28+ twoPlusTwo : 2 + 2 = 4
29+ twoPlusTwo = Refl
30+
31+.. _sect-empty:
32+
33+The Empty Type
34+--------------
35+
36+There is an empty type, :math:`\bot`, which has no constructors. It is
37+therefore impossible to construct an element of the empty type, at least
38+without using a partially defined or general recursive function (see
39+Section :ref:`sect-totality` for more details). We can therefore use the
40+empty type to prove that something is impossible, for example zero is
41+never equal to a successor:
42+
43+.. code-block:: idris
44+
45+ disjoint : (n : Nat) -> Z = S n -> Void
46+ disjoint n p = replace {P = disjointTy} p ()
47+ where
48+ disjointTy : Nat -> Type
49+ disjointTy Z = ()
50+ disjointTy (S k) = Void
51+
52+There is no need to worry too much about how this function works —
53+essentially, it applies the library function ``replace``, which uses an
54+equality proof to transform a predicate. Here we use it to transform a
55+value of a type which can exist, the empty tuple, to a value of a type
56+which can’t, by using a proof of something which can’t exist.
57+
58+Once we have an element of the empty type, we can prove anything.
59+``void`` is defined in the library, to assist with proofs by
60+contradiction.
61+
62+.. code-block:: idris
63+
64+ void : Void -> a
65+
66+Simple Theorems
67+---------------
68+
69+When type checking dependent types, the type itself gets *normalised*.
70+So imagine we want to prove the following theorem about the reduction
71+behaviour of ``plus``:
72+
73+.. code-block:: idris
74+
75+ plusReduces : (n:Nat) -> plus Z n = n
76+
77+We’ve written down the statement of the theorem as a type, in just the
78+same way as we would write the type of a program. In fact there is no
79+real distinction between proofs and programs. A proof, as far as we are
80+concerned here, is merely a program with a precise enough type to
81+guarantee a particular property of interest.
82+
83+We won’t go into details here, but the Curry-Howard correspondence [1]_
84+explains this relationship. The proof itself is trivial, because
85+``plus Z n`` normalises to ``n`` by the definition of ``plus``:
86+
87+.. code-block:: idris
88+
89+ plusReduces n = Refl
90+
91+It is slightly harder if we try the arguments the other way, because
92+plus is defined by recursion on its first argument. The proof also works
93+by recursion on the first argument to ``plus``, namely ``n``.
94+
95+.. code-block:: idris
96+
97+ plusReducesZ : (n:Nat) -> n = plus n Z
98+ plusReducesZ Z = Refl
99+ plusReducesZ (S k) = cong (plusReducesZ k)
100+
101+``cong`` is a function defined in the library which states that equality
102+respects function application:
103+
104+.. code-block:: idris
105+
106+ cong : {f : t -> u} -> a = b -> f a = f b
107+
108+We can do the same for the reduction behaviour of plus on successors:
109+
110+.. code-block:: idris
111+
112+ plusReducesS : (n:Nat) -> (m:Nat) -> S (plus n m) = plus n (S m)
113+ plusReducesS Z m = Refl
114+ plusReducesS (S k) m = cong (plusReducesS k m)
115+
116+Even for trival theorems like these, the proofs are a little tricky to
117+construct in one go. When things get even slightly more complicated, it
118+becomes too much to think about to construct proofs in this ‘batch
119+mode’.
120+
121+Idris provides interactive editing capabilities, which can help with
122+building proofs. For more details on building proofs interactively in
123+an editor, see :ref:`proofs-index`. In the rest of this section, we discuss
124+Idris's interactive proof mode.
125+
126+Interactive theorem proving
127+---------------------------
128+
129+Instead of writing the proof in one go, we can use Idris’s interactive proof
130+mode. To do this, we write the general *structure* of the proof, and use
131+the interactive mode to complete the details. We’ll be constructing the
132+proof by *induction*, so we write the cases for ``Z`` and ``S``, with a
133+recursive call in the ``S`` case giving the inductive hypothesis, and
134+insert *metavariables* for the rest of the definition:
135+
136+.. code-block:: idris
137+
138+ plusReducesZ' : (n:Nat) -> n = plus n Z
139+ plusReducesZ' Z = ?plusredZ_Z
140+ plusReducesZ' (S k) = let ih = plusReducesZ' k in
141+ ?plusredZ_S
142+
143+On running , two global names are created, ``plusredZ_Z`` and
144+``plusredZ_S``, with no definition. We can use the ``:m`` command at the
145+prompt to find out which metavariables are still to be solved (or, more
146+precisely, which functions exist but have no definitions), then the
147+``:t`` command to see their types:
148+
149+.. code-block:: idris
150+
151+ *theorems> :m
152+ Global metavariables:
153+ [plusredZ_S,plusredZ_Z]
154+
155+.. code-block:: idris
156+
157+ *theorems> :t plusredZ_Z
158+ plusredZ_Z : Z = plus Z Z
159+
160+ *theorems> :t plusredZ_S
161+ plusredZ_S : (k : Nat) -> (k = plus k Z) -> S k = plus (S k) Z
162+
163+The ``:p`` command enters interactive proof mode, which can be used to
164+complete the missing definitions.
165+
166+.. code-block:: idris
167+
168+ *theorems> :p plusredZ_Z
169+
170+ ---------------------------------- (plusredZ_Z) --------
171+ {hole0} : Z = plus Z Z
172+
173+This gives us a list of premises (above the line; there are none here)
174+and the current goal (below the line; named ``{hole0}`` here). At the
175+prompt we can enter tactics to direct the construction of the proof. In
176+this case, we can normalise the goal with the ``compute`` tactic:
177+
178+.. code-block:: idris
179+
180+ -plusredZ_Z> compute
181+
182+ ---------------------------------- (plusredZ_Z) --------
183+ {hole0} : Z = Z
184+
185+Now we have to prove that ``Z`` equals ``Z``, which is easy to prove by
186+``Refl``. To apply a function, such as ``Refl``, we use ``refine`` which
187+introduces subgoals for each of the function’s explicit arguments
188+(``Refl`` has none):
189+
190+.. code-block:: idris
191+
192+ -plusredZ_Z> refine Refl
193+ plusredZ_Z: no more goals
194+
195+Here, we could also have used the ``trivial`` tactic, which tries to
196+refine by ``Refl``, and if that fails, tries to refine by each name in
197+the local context. When a proof is complete, we use the ``qed`` tactic
198+to add the proof to the global context, and remove the metavariable from
199+the unsolved metavariables list. This also outputs a trace of the proof:
200+
201+.. code-block:: idris
202+
203+ -plusredZ_Z> qed
204+ plusredZ_Z = proof
205+ compute
206+ refine Refl
207+
208+.. code-block:: idris
209+
210+ *theorems> :m
211+ Global metavariables:
212+ [plusredZ_S]
213+
214+The ``:addproof`` command, at the interactive prompt, will add the proof
215+to the source file (effectively in an appendix). Let us now prove the
216+other required lemma, ``plusredZ_S``:
217+
218+.. code-block:: idris
219+
220+ *theorems> :p plusredZ_S
221+
222+ ---------------------------------- (plusredZ_S) --------
223+ {hole0} : (k : Nat) -> (k = plus k Z) -> S k = plus (S k) Z
224+
225+In this case, the goal is a function type, using ``k`` (the argument
226+accessible by pattern matching) and ``ih`` — the local variable
227+containing the result of the recursive call. We can introduce these as
228+premisses using the ``intro`` tactic twice (or ``intros``, which
229+introduces all arguments as premisses). This gives:
230+
231+.. code-block:: idris
232+
233+ k : Nat
234+ ih : k = plus k Z
235+ ---------------------------------- (plusredZ_S) --------
236+ {hole2} : S k = plus (S k) Z
237+
238+Since plus is defined by recursion on its first argument, the term
239+``plus (S k) Z`` in the goal can be simplified, so we use ``compute``.
240+
241+.. code-block:: idris
242+
243+ k : Nat
244+ ih : k = plus k Z
245+ ---------------------------------- (plusredZ_S) --------
246+ {hole2} : S k = S (plus k Z)
247+
248+We know, from the type of ``ih``, that ``k = plus k Z``, so we would
249+like to use this knowledge to replace ``plus k Z`` in the goal with
250+``k``. We can achieve this with the ``rewrite`` tactic:
251+
252+.. code-block:: idris
253+
254+ -plusredZ_S> rewrite ih
255+
256+ k : Nat
257+ ih : k = plus k Z
258+ ---------------------------------- (plusredZ_S) --------
259+ {hole3} : S k = S k
260+
261+ -plusredZ_S>
262+
263+The ``rewrite`` tactic takes an equality proof as an argument, and tries
264+to rewrite the goal using that proof. Here, it results in an equality
265+which is trivially provable:
266+
267+.. code-block:: idris
268+
269+ -plusredZ_S> trivial
270+ plusredZ_S: no more goals
271+ -plusredZ_S> qed
272+ plusredZ_S = proof {
273+ intros;
274+ rewrite ih;
275+ trivial;
276+ }
277+
278+Again, we can add this proof to the end of our source file using the
279+``:addproof`` command at the interactive prompt.
280+
281+.. _sect-totality:
282+
283+Totality Checking
284+-----------------
285+
286+If we really want to trust our proofs, it is important that they are
287+defined by *total* functions — that is, a function which is defined for
288+all possible inputs and is guaranteed to terminate. Otherwise we could
289+construct an element of the empty type, from which we could prove
290+anything:
291+
292+.. code-block:: idris
293+
294+ -- making use of 'hd' being partially defined
295+ empty1 : Void
296+ empty1 = hd [] where
297+ hd : List a -> a
298+ hd (x :: xs) = x
299+
300+ -- not terminating
301+ empty2 : Void
302+ empty2 = empty2
303+
304+Internally, Idris checks every definition for totality, and we can check at
305+the prompt with the ``:total`` command. We see that neither of the above
306+definitions is total:
307+
308+::
309+
310+ *theorems> :total empty1
311+ possibly not total due to: empty1#hd
312+ not total as there are missing cases
313+ *theorems> :total empty2
314+ possibly not total due to recursive path empty2
315+
316+Note the use of the word “possibly” — a totality check can, of course,
317+never be certain due to the undecidability of the halting problem. The
318+check is, therefore, conservative. It is also possible (and indeed
319+advisable, in the case of proofs) to mark functions as total so that it
320+will be a compile time error for the totality check to fail:
321+
322+.. code-block:: idris
323+
324+ total empty2 : Void
325+ empty2 = empty2
326+
327+::
328+
329+ Type checking ./theorems.idr
330+ theorems.idr:25:empty2 is possibly not total due to recursive path empty2
331+
332+Reassuringly, our proof in Section :ref:`sect-empty` that the zero and
333+successor constructors are disjoint is total:
334+
335+.. code-block:: idris
336+
337+ *theorems> :total disjoint
338+ Total
339+
340+The totality check is, necessarily, conservative. To be recorded as
341+total, a function ``f`` must:
342+
343+- Cover all possible inputs
344+
345+- Be *well-founded* — i.e. by the time a sequence of (possibly
346+ mutually) recursive calls reaches ``f`` again, it must be possible to
347+ show that one of its arguments has decreased.
348+
349+- Not use any data types which are not *strictly positive*
350+
351+- Not call any non-total functions
352+
353+Directives and Compiler Flags for Totality
354+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
355+
356+By default, Idris allows all well-typed definitions, whether total or not.
357+However, it is desirable for functions to be total as far as possible, as this
358+provides a guarantee that they provide a result for all possible inputs, in
359+finite time. It is possible to make total functions a requirement, either:
360+
361+- By using the ``--total`` compiler flag.
362+
363+- By adding a ``%default total`` directive to a source file. All
364+ definitions after this will be required to be total, unless
365+ explicitly flagged as ``partial``.
366+
367+All functions *after* a ``%default total`` declaration are required to
368+be total. Correspondingly, after a ``%default partial`` declaration, the
369+requirement is relaxed.
370+
371+Finally, the compiler flag ``--warnpartial`` causes to print a warning
372+for any undeclared partial function.
373+
374+Totality checking issues
375+~~~~~~~~~~~~~~~~~~~~~~~~
376+
377+Please note that the totality checker is not perfect! Firstly, it is
378+necessarily conservative due to the undecidability of the halting
379+problem, so many programs which *are* total will not be detected as
380+such. Secondly, the current implementation has had limited effort put
381+into it so far, so there may still be cases where it believes a function
382+is total which is not. Do not rely on it for your proofs yet!
383+
384+Hints for totality
385+~~~~~~~~~~~~~~~~~~
386+
387+In cases where you believe a program is total, but Idris does not agree, it is
388+possible to give hints to the checker to give more detail for a termination
389+argument. The checker works by ensuring that all chains of recursive calls
390+eventually lead to one of the arguments decreasing towards a base case, but
391+sometimes this is hard to spot. For example, the following definition cannot be
392+checked as ``total`` because the checker cannot decide that ``filter (<= x) xs``
393+will always be smaller than ``(x :: xs)``:
394+
395+.. code-block:: idris
396+
397+ qsort : Ord a => List a -> List a
398+ qsort [] = []
399+ qsort (x :: xs)
400+ = qsort (filter (< x) xs) ++
401+ (x :: qsort (filter (>= x) xs))
402+
403+The function ``assert_smaller``, defined in the Prelude, is intended to
404+address this problem:
405+
406+.. code-block:: idris
407+
408+ assert_smaller : a -> a -> a
409+ assert_smaller x y = y
410+
411+It simply evaluates to its second argument, but also asserts to the
412+totality checker that ``y`` is structurally smaller than ``x``. This can
413+be used to explain the reasoning for totality if the checker cannot work
414+it out itself. The above example can now be written as:
415+
416+.. code-block:: idris
417+
418+ total
419+ qsort : Ord a => List a -> List a
420+ qsort [] = []
421+ qsort (x :: xs)
422+ = qsort (assert_smaller (x :: xs) (filter (< x) xs)) ++
423+ (x :: qsort (assert_smaller (x :: xs) (filter (>= x) xs)))
424+
425+The expression ``assert_smaller (x :: xs) (filter (<= x) xs)`` asserts
426+that the result of the filter will always be smaller than the pattern
427+``(x :: xs)``.
428+
429+In more extreme cases, the function ``assert_total`` marks a
430+subexpression as always being total:
431+
432+.. code-block:: idris
433+
434+ assert_total : a -> a
435+ assert_total x = x
436+
437+In general, this function should be avoided, but it can be very useful
438+when reasoning about primitives or externally defined functions (for
439+example from a C library) where totality can be shown by an external
440+argument.
441+
442+
443+.. [1] Timothy G. Griffin. 1989. A formulae-as-type notion of
444+ control. In Proceedings of the 17th ACM SIGPLAN-SIGACT
445+ symposium on Principles of programming languages (POPL
446+ '90). ACM, New York, NY, USA, 47-58. DOI=10.1145/96709.96714
447+ http://doi.acm.org/10.1145/96709.96714
docs/tutorial/typesfuns.rstnew file+1048
@@ -0,0 +1,1048 @@
1+.. _sect-typefuns:
2+
3+===================
4+Types and Functions
5+===================
6+
7+Primitive Types
8+---------------
9+
10+Idris defines several primitive types: ``Int``, ``Integer`` and
11+``Float`` for numeric operations, ``Char`` and ``String`` for text
12+manipulation, and ``Ptr`` which represents foreign pointers. There are
13+also several data types declared in the library, including ``Bool``,
14+with values ``True`` and ``False``. We can declare some constants with
15+these types. Enter the following into a file ``prims.idr`` and load it
16+into the Idris interactive environment by typing ``idris
17+prims.idr``:
18+
19+.. code-block:: idris
20+
21+ module prims
22+
23+ x : Int
24+ x = 42
25+
26+ foo : String
27+ foo = "Sausage machine"
28+
29+ bar : Char
30+ bar = 'Z'
31+
32+ quux : Bool
33+ quux = False
34+
35+An Idris file consists of an optional module declaration (here
36+``module prims``) followed by an optional list of imports (none here,
37+however Idris programs can consist of several modules, and the
38+definitions in each module each have their own namespace, as we will
39+discuss in Section :ref:`sect-namespaces`) and a collection of
40+declarations and definitions. The order of definitions is significant
41+— functions and data types must be defined before use. Each definition
42+must have a type declaration, for example see ``x : Int``, ``foo :
43+String``, from the above listing. Indentation is significant — a new
44+declaration begins at the same level of indentation as the preceding
45+declaration. Alternatively, declarations may be terminated with a
46+semicolon.
47+
48+A library module ``prelude`` is automatically imported by every
49+Idris program, including facilities for IO, arithmetic, data
50+structures and various common functions. The prelude defines several
51+arithmetic and comparison operators, which we can use at the prompt.
52+Evaluating things at the prompt gives an answer, and the type of the
53+answer. For example:
54+
55+::
56+
57+ *prims> 6*6+6
58+ 42 : Int
59+ *prims> x == 6*6+6
60+ True : Bool
61+
62+All of the usual arithmetic and comparison operators are defined for
63+the primitive types. They are overloaded using type classes, as we
64+will discuss in Section :ref:`sect-classes` and can be extended to
65+work on user defined types. Boolean expressions can be tested with the
66+``if...then...else`` construct:
67+
68+::
69+
70+ *prims> if x == 6 * 6 + 6 then "The answer!" else "Not the answer"
71+ "The answer!" : String
72+
73+Data Types
74+----------
75+
76+Data types are declared in a similar way to Haskell data types, with a
77+similar syntax. Natural numbers and lists, for example, can be
78+declared as follows:
79+
80+.. code-block:: idris
81+
82+ data Nat = Z | S Nat -- Natural numbers
83+ -- (zero and successor)
84+ data List a = Nil | (::) a (List a) -- Polymorphic lists
85+
86+The above declarations are taken from the standard library. Unary
87+natural numbers can be either zero (``Z``), or the successor of
88+another natural number (``S k``). Lists can either be empty (``Nil``)
89+or a value added to the front of another list (``x :: xs``). In the
90+declaration for ``List``, we used an infix operator ``::``. New
91+operators such as this can be added using a fixity declaration, as
92+follows:
93+
94+::
95+
96+ infixr 10 ::
97+
98+Functions, data constructors and type constructors may all be given
99+infix operators as names. They may be used in prefix form if enclosed
100+in brackets, e.g. ``(::)``. Infix operators can use any of the
101+symbols:
102+
103+::
104+
105+ :+-*/=_.?|&><!@$%^~.
106+
107+Functions
108+---------
109+
110+Functions are implemented by pattern matching, again using a similar
111+syntax to Haskell. The main difference is that Idris requires type
112+declarations for all functions, using a single colon ``:`` (rather
113+than Haskell’s double colon ``::``). Some natural number arithmetic
114+functions can be defined as follows, again taken from the standard
115+library:
116+
117+.. code-block:: idris
118+
119+ -- Unary addition
120+ plus : Nat -> Nat -> Nat
121+ plus Z y = y
122+ plus (S k) y = S (plus k y)
123+
124+ -- Unary multiplication
125+ mult : Nat -> Nat -> Nat
126+ mult Z y = Z
127+ mult (S k) y = plus y (mult k y)
128+
129+The standard arithmetic operators ``+`` and ``*`` are also overloaded
130+for use by ``Nat``, and are implemented using the above functions.
131+Unlike Haskell, there is no restriction on whether types and function
132+names must begin with a capital letter or not. Function names
133+(``plus`` and ``mult`` above), data constructors (``Z``, ``S``,
134+``Nil`` and ``::``) and type constructors (``Nat`` and ``List``) are
135+all part of the same namespace. We can test these functions at the
136+Idris prompt:
137+
138+::
139+
140+ Idris> plus (S (S Z)) (S (S Z))
141+ 4 : Nat
142+ Idris> mult (S (S (S Z))) (plus (S (S Z)) (S (S Z)))
143+ 12 : Nat
144+
145+.. note::
146+
147+ Idris automatically desugars the ``Nat`` representation into a
148+ more human readable format. The result of ``plus (S (S Z)) (S (S Z))``
149+ is actually ``(S (S (S (S Z))))`` which is the Integer 4. This can be
150+ checked at the Idris prompt:
151+
152+::
153+
154+ Idris> (S (S (S (S Z))))
155+ 4 : Nat
156+
157+Like arithmetic operations, integer literals are also overloaded using
158+type classes, meaning that we can also test the functions as follows:
159+
160+::
161+
162+ Idris> plus 2 2
163+ 4 : Nat
164+ Idris> mult 3 (plus 2 2)
165+ 12 : Nat
166+
167+You may wonder, by the way, why we have unary natural numbers when our
168+computers have perfectly good integer arithmetic built in. The reason
169+is primarily that unary numbers have a very convenient structure which
170+is easy to reason about, and easy to relate to other data structures
171+as we will see later. Nevertheless, we do not want this convenience to
172+be at the expense of efficiency. Fortunately, Idris knows about
173+the relationship between ``Nat`` (and similarly structured types) and
174+numbers. This means it can optimise the representation, and functions
175+such as ``plus`` and ``mult``.
176+
177+``where`` clauses
178+~~~~~~~~~~~~~~~~~
179+
180+Functions can also be defined *locally* using ``where`` clauses. For
181+example, to define a function which reverses a list, we can use an
182+auxiliary function which accumulates the new, reversed list, and which
183+does not need to be visible globally:
184+
185+.. code-block:: idris
186+
187+ reverse : List a -> List a
188+ reverse xs = revAcc [] xs where
189+ revAcc : List a -> List a -> List a
190+ revAcc acc [] = acc
191+ revAcc acc (x :: xs) = revAcc (x :: acc) xs
192+
193+Indentation is significant — functions in the ``where`` block must be
194+indented further than the outer function.
195+
196+**Scope:** Any names which are visible in the outer scope are also
197+visible in the ``where`` clause (unless they have been redefined, such
198+as ``xs`` here). A name which appears only in the type will be in scope
199+in the ``where`` clause if it is a *parameter* to one of the types,
200+i.e. it is fixed across the entire structure.
201+
202+As well as functions, ``where`` blocks can include local data
203+declarations, such as the following where ``MyLT`` is not accessible
204+outside the definition of ``foo``:
205+
206+.. code-block:: idris
207+
208+ foo : Int -> Int
209+ foo x = case isLT of
210+ Yes => x*2
211+ No => x*4
212+ where
213+ data MyLT = Yes | No
214+
215+ isLT : MyLT
216+ isLT = if x < 20 then Yes else No
217+
218+In general, functions defined in a ``where`` clause need a type
219+declaration just like any top level function. However, the type
220+declaration for a function ``f`` *can* be omitted if:
221+
222+- ``f`` appears in the right hand side of the top level definition
223+
224+- The type of ``f`` can be completely determined from its first application
225+
226+
227+So, for example, the following definitions are legal:
228+
229+.. code-block:: idris
230+
231+ even : Nat -> Bool
232+ even Z = True
233+ even (S k) = odd k where
234+ odd Z = False
235+ odd (S k) = even k
236+
237+ test : List Nat
238+ test = [c (S 1), c Z, d (S Z)]
239+ where c x = 42 + x
240+ d y = c (y + 1 + z y)
241+ where z w = y + w
242+
243+Dependent Types
244+---------------
245+
246+Vectors
247+~~~~~~~
248+
249+A standard example of a dependent type is the type of “lists with
250+length”, conventionally called vectors in the dependent type
251+literature. They are available as part of the Idris library, by
252+importing ``Data.Vect``, or we can declare them as follows:
253+
254+.. code-block:: idris
255+
256+ data Vect : Nat -> Type -> Type where
257+ Nil : Vect Z a
258+ (::) : a -> Vect k a -> Vect (S k) a
259+
260+Note that we have used the same constructor names as for ``List``.
261+Ad-hoc name overloading such as this is accepted by Idris,
262+provided that the names are declared in different namespaces (in
263+practice, normally in different modules). Ambiguous constructor names
264+can normally be resolved from context.
265+
266+This declares a family of types, and so the form of the declaration is
267+rather different from the simple type declarations above. We
268+explicitly state the type of the type constructor ``Vect`` — it takes
269+a ``Nat`` and a type as an argument, where ``Type`` stands for the
270+type of types. We say that ``Vect`` is *indexed* over ``Nat`` and
271+*parameterised* by ``Type``. Each constructor targets a different part
272+of the family of types. ``Nil`` can only be used to construct vectors
273+with zero length, and ``::`` to construct vectors with non-zero
274+length. In the type of ``::``, we state explicitly that an element of
275+type ``a`` and a tail of type ``Vect k a`` (i.e., a vector of length
276+``k``) combine to make a vector of length ``S k``.
277+
278+We can define functions on dependent types such as ``Vect`` in the same
279+way as on simple types such as ``List`` and ``Nat`` above, by pattern
280+matching. The type of a function over ``Vect`` will describe what
281+happens to the lengths of the vectors involved. For example, ``++``,
282+defined as follows, appends two ``Vect``:
283+
284+.. code-block:: idris
285+
286+ (++) : Vect n a -> Vect m a -> Vect (n + m) a
287+ (++) Nil ys = ys
288+ (++) (x :: xs) ys = x :: xs ++ ys
289+
290+The type of ``(++)`` states that the resulting vector’s length will be
291+the sum of the input lengths. If we get the definition wrong in such a
292+way that this does not hold, Idris will not accept the definition.
293+For example:
294+
295+.. code-block:: idris
296+
297+ (++) : Vect n a -> Vect m a -> Vect (n + m) a
298+ (++) Nil ys = ys
299+ (++) (x :: xs) ys = x :: xs ++ xs -- BROKEN
300+
301+When run through the Idris type checker, this results in the
302+following:
303+
304+::
305+
306+ $ idris vbroken.idr --check
307+ vbroken.idr:9:23:When elaborating right hand side of Vect.++:
308+ When elaborating an application of constructor Vect.:::
309+ Can't unify
310+ Vect (k + k) a
311+ with
312+ Vect (plus k m) a
313+
314+ Specifically:
315+ Can't unify
316+ plus k k
317+ with
318+ plus k m
319+
320+This error message suggests that there is a length mismatch between
321+two vectors — we needed a vector of length ``k + m``, but provided a
322+vector of length ``k + k``.
323+
324+The Finite Sets
325+~~~~~~~~~~~~~~~
326+
327+Finite sets, as the name suggests, are sets with a finite number of
328+elements. They are available as part of the Idris library, by
329+importing ``Data.Fin``, or can be declared as follows:
330+
331+.. code-block:: idris
332+
333+ data Fin : Nat -> Type where
334+ FZ : Fin (S k)
335+ FS : Fin k -> Fin (S k)
336+
337+``FZ`` is the zeroth element of a finite set with ``S k`` elements;
338+``FS n`` is the ``n+1``\ th element of a finite set with ``S k``
339+elements. ``Fin`` is indexed by a ``Nat``, which represents the number
340+of elements in the set. Obviously we can’t construct an element of an
341+empty set, so neither constructor targets ``Fin Z``.
342+
343+A useful application of the ``Fin`` family is to represent bounded
344+natural numbers. Since the first ``n`` natural numbers form a finite
345+set of ``n`` elements, we can treat ``Fin n`` as the set of natural
346+numbers bounded by ``n``.
347+
348+For example, the following function which looks up an element in a
349+``Vect``, by a bounded index given as a ``Fin n``, is defined in the
350+prelude:
351+
352+.. code-block:: idris
353+
354+ index : Fin n -> Vect n a -> a
355+ index FZ (x :: xs) = x
356+ index (FS k) (x :: xs) = index k xs
357+
358+This function looks up a value at a given location in a vector. The
359+location is bounded by the length of the vector (``n`` in each case),
360+so there is no need for a run-time bounds check. The type checker
361+guarantees that the location is no larger than the length of the
362+vector.
363+
364+Note also that there is no case for ``Nil`` here. This is because it
365+is impossible. Since there is no element of ``Fin Z``, and the
366+location is a ``Fin n``, then ``n`` can not be ``Z``. As a result,
367+attempting to look up an element in an empty vector would give a
368+compile time type error, since it would force ``n`` to be ``Z``.
369+
370+Implicit Arguments
371+~~~~~~~~~~~~~~~~~~
372+
373+Let us take a closer look at the type of ``index``:
374+
375+.. code-block:: idris
376+
377+ index : Fin n -> Vect n a -> a
378+
379+It takes two arguments, an element of the finite set of ``n`` elements,
380+and a vector with ``n`` elements of type ``a``. But there are also two
381+names, ``n`` and ``a``, which are not declared explicitly. These are
382+*implicit* arguments to ``index``. We could also write the type of
383+``index`` as:
384+
385+.. code-block:: idris
386+
387+ index : {a:Type} -> {n:Nat} -> Fin n -> Vect n a -> a
388+
389+Implicit arguments, given in braces ``{}`` in the type declaration,
390+are not given in applications of ``index``; their values can be
391+inferred from the types of the ``Fin n`` and ``Vect n a``
392+arguments. Any name with a which appears as a parameter or index in a
393+type declaration, but which is otherwise free, will be automatically
394+bound as an implicit argument. Implicit arguments can still be given
395+explicitly in applications, using ``{a=value}`` and ``{n=value}``, for
396+example:
397+
398+.. code-block:: idris
399+
400+ index {a=Int} {n=2} FZ (2 :: 3 :: Nil)
401+
402+In fact, any argument, implicit or explicit, may be given a name. We
403+could have declared the type of ``index`` as:
404+
405+.. code-block:: idris
406+
407+ index : (i:Fin n) -> (xs:Vect n a) -> a
408+
409+It is a matter of taste whether you want to do this — sometimes it can
410+help document a function by making the purpose of an argument more
411+clear.
412+
413+“``using``” notation
414+~~~~~~~~~~~~~~~~~~~~
415+
416+Sometimes it is useful to provide types of implicit arguments,
417+particularly where there is a dependency ordering, or where the
418+implicit arguments themselves have dependencies. For example, we may
419+wish to state the types of the implicit arguments in the following
420+definition, which defines a predicate on vectors:
421+
422+.. code-block:: idris
423+
424+ data Elem : a -> Vect n a -> Type where
425+ Here : {x:a} -> {xs:Vect n a} -> Elem x (x :: xs)
426+ There : {x,y:a} -> {xs:Vect n a} -> Elem x xs -> Elem x (y :: xs)
427+
428+An instance of ``Elem x xs`` states that ``x`` is an element of
429+``xs``. We can construct such a predicate if the required element is
430+``Here``, at the head of the vector, or ``There``, in the tail of the
431+vector. For example:
432+
433+.. code-block:: idris
434+
435+ testVec : Vect 4 Int
436+ testVec = 3 :: 4 :: 5 :: 6 :: Nil
437+
438+ inVect : Elem 5 testVec
439+ inVect = There (There Here)
440+
441+If the same implicit arguments are being used a lot, it can make a
442+definition difficult to read. To avoid this problem, a ``using`` block
443+gives the types and ordering of any implicit arguments which can
444+appear within the block:
445+
446+.. code-block:: idris
447+
448+ using (x:a, y:a, xs:Vect n a)
449+ data Elem : a -> Vect n a -> Type where
450+ Here : Elem x (x :: xs)
451+ There : Elem x xs -> Elem x (y :: xs)
452+
453+Note: Declaration Order and ``mutual`` blocks
454+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
455+
456+In general, functions and data types must be defined before use, since
457+dependent types allow functions to appear as part of types, and their
458+reduction behaviour to affect type checking. However, this restriction
459+can be relaxed by using a ``mutual`` block, which allows data types
460+and functions to be defined simultaneously:
461+
462+.. code-block:: idris
463+
464+ mutual
465+ even : Nat -> Bool
466+ even Z = True
467+ even (S k) = odd k
468+
469+ odd : Nat -> Bool
470+ odd Z = False
471+ odd (S k) = even k
472+
473+In a ``mutual`` block, first all of the type declarations are added,
474+then the function bodies. As a result, none of the function types can
475+depend on the reduction behaviour of any of the functions in the
476+block.
477+
478+I/O
479+---
480+
481+Computer programs are of little use if they do not interact with the
482+user or the system in some way. The difficulty in a pure language such
483+as Idris — that is, a language where expressions do not have
484+side-effects — is that I/O is inherently side-effecting. Therefore in
485+Idris, such interactions are encapsulated in the type ``IO``:
486+
487+.. code-block:: idris
488+
489+ data IO a -- IO operation returning a value of type a
490+
491+We’ll leave the definition of ``IO`` abstract, but effectively it
492+describes what the I/O operations to be executed are, rather than how
493+to execute them. The resulting operations are executed externally, by
494+the run-time system. We’ve already seen one IO program:
495+
496+.. code-block:: idris
497+
498+ main : IO ()
499+ main = putStrLn "Hello world"
500+
501+The type of ``putStrLn`` explains that it takes a string, and returns
502+an element of the unit type ``()`` via an I/O action. There is a
503+variant ``putStr`` which outputs a string without a newline:
504+
505+.. code-block:: idris
506+
507+ putStrLn : String -> IO ()
508+ putStr : String -> IO ()
509+
510+We can also read strings from user input:
511+
512+.. code-block:: idris
513+
514+ getLine : IO String
515+
516+A number of other I/O operations are defined in the prelude, for
517+example for reading and writing files, including:
518+
519+.. code-block:: idris
520+
521+ data File -- abstract
522+ data Mode = Read | Write | ReadWrite
523+
524+ openFile : String -> Mode -> IO File
525+ closeFile : File -> IO ()
526+
527+ fread : File -> IO String
528+ fwrite : File -> String -> IO ()
529+ feof : File -> IO Bool
530+
531+ readFile : String -> IO String
532+
533+.. _sect-do:
534+
535+“``do``” notation
536+-----------------
537+
538+I/O programs will typically need to sequence actions, feeding the
539+output of one computation into the input of the next. ``IO`` is an
540+abstract type, however, so we can’t access the result of a computation
541+directly. Instead, we sequence operations with ``do`` notation:
542+
543+.. code-block:: idris
544+
545+ greet : IO ()
546+ greet = do putStr "What is your name? "
547+ name <- getLine
548+ putStrLn ("Hello " ++ name)
549+
550+The syntax ``x <- iovalue`` executes the I/O operation ``iovalue``, of
551+type ``IO a``, and puts the result, of type ``a`` into the variable
552+``x``. In this case, ``getLine`` returns an ``IO String``, so ``name``
553+has type ``String``. Indentation is significant — each statement in
554+the do block must begin in the same column. The ``return`` operation
555+allows us to inject a value directly into an IO operation:
556+
557+.. code-block:: idris
558+
559+ return : a -> IO a
560+
561+As we will see later, ``do`` notation is more general than this, and
562+can be overloaded.
563+
564+.. _sect-lazy:
565+
566+Laziness
567+--------
568+
569+Normally, arguments to functions are evaluated before the function
570+itself (that is, Idris uses *eager* evaluation). However, this is
571+not always the best approach. Consider the following function:
572+
573+.. code-block:: idris
574+
575+ boolCase : Bool -> a -> a -> a;
576+ boolCase True t e = t;
577+ boolCase False t e = e;
578+
579+This function uses one of the ``t`` or ``e`` arguments, but not both
580+(in fact, this is used to implement the ``if...then...else`` construct
581+as we will see later. We would prefer if *only* the argument which was
582+used was evaluated. To achieve this, Idris provides a ``Lazy``
583+data type, which allows evaluation to be suspended:
584+
585+.. code-block:: idris
586+
587+ data Lazy : Type -> Type where
588+ Delay : (val : a) -> Lazy a
589+
590+ Force : Lazy a -> a
591+
592+A value of type ``Lazy a`` is unevaluated until it is forced by
593+``Force``. The Idris type checker knows about the ``Lazy`` type,
594+and inserts conversions where necessary between ``Lazy a`` and ``a``,
595+and vice versa. We can therefore write ``boolCase`` as follows,
596+without any explicit use of ``Force`` or ``Delay``:
597+
598+.. code-block:: idris
599+
600+ boolCase : Bool -> Lazy a -> Lazy a -> a;
601+ boolCase True t e = t;
602+ boolCase False t e = e;
603+
604+Useful Data Types
605+-----------------
606+
607+Idris includes a number of useful data types and library functions
608+(see the ``libs/`` directory in the distribution). This chapter
609+describes a few of these. The functions described here are imported
610+automatically by every Idris program, as part of ``Prelude.idr``.
611+
612+``List`` and ``Vect``
613+~~~~~~~~~~~~~~~~~~~~~
614+
615+We have already seen the ``List`` and ``Vect`` data types:
616+
617+.. code-block:: idris
618+
619+ data List a = Nil | (::) a (List a)
620+
621+ data Vect : Nat -> Type -> Type where
622+ Nil : Vect Z a
623+ (::) : a -> Vect k a -> Vect (S k) a
624+
625+Note that the constructor names are the same for each — constructor
626+names (in fact, names in general) can be overloaded, provided that
627+they are declared in different namespaces (see Section
628+:ref:`sect-namespaces`), and will typically be resolved according to
629+their type. As syntactic sugar, any type with the constructor names
630+``Nil`` and ``::`` can be written in list form. For example:
631+
632+- ``[]`` means ``Nil``
633+
634+- ``[1,2,3]`` means ``1 :: 2 :: 3 :: Nil``
635+
636+The library also defines a number of functions for manipulating these
637+types. ``map`` is overloaded both for ``List`` and ``Vect`` and
638+applies a function to every element of the list or vector.
639+
640+.. code-block:: idris
641+
642+ map : (a -> b) -> List a -> List b
643+ map f [] = []
644+ map f (x :: xs) = f x :: map f xs
645+
646+ map : (a -> b) -> Vect n a -> Vect n b
647+ map f [] = []
648+ map f (x :: xs) = f x :: map f xs
649+
650+For example, given the following vector of integers, and a function to
651+double an integer:
652+
653+.. code-block:: idris
654+
655+ intVec : Vect 5 Int
656+ intVec = [1, 2, 3, 4, 5]
657+
658+ double : Int -> Int
659+ double x = x * 2
660+
661+the function ``map`` can be used as follows to double every element in
662+the vector:
663+
664+::
665+
666+ *usefultypes> show (map double intVec)
667+ "[2, 4, 6, 8, 10]" : String
668+
669+You’ll find these examples in ``usefultypes.idr`` in the ``examples/``
670+directory. For more details of the functions available on ``List`` and
671+``Vect``, look in the library files:
672+
673+- ``libs/prelude/Prelude/List.idr``
674+
675+- ``libs/base/Data/List.idr``
676+
677+- ``libs/base/Data/Vect.idr``
678+
679+- ``libs/base/Data/VectType.idr``
680+
681+Functions include filtering, appending, reversing, and so on. Also
682+remember that Idris is still in development, so if you don’t see
683+the function you need, please feel free to add it and submit a patch!
684+
685+Aside: Anonymous functions and operator sections
686+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
687+
688+There are actually neater ways to write the above expression. One way
689+would be to use an anonymous function:
690+
691+::
692+
693+ *usefultypes> show (map (\x => x * 2) intVec)
694+ "[2, 4, 6, 8, 10]" : String
695+
696+The notation ``\x => val`` constructs an anonymous function which takes
697+one argument, ``x`` and returns the expression ``val``. Anonymous
698+functions may take several arguments, separated by commas,
699+e.g. ``\x, y, z => val``. Arguments may also be given explicit types,
700+e.g. ``\x : Int => x * 2``, and can pattern match,
701+e.g. ``\(x, y) => x + y``. We could also use an operator section:
702+
703+::
704+
705+ *usefultypes> show (map (* 2) intVec)
706+ "[2, 4, 6, 8, 10]" : String
707+
708+``(*2)`` is shorthand for a function which multiplies a number
709+by 2. It expands to ``\x => x * 2``. Similarly, ``(2*)`` would expand
710+to ``\x => 2 * x``.
711+
712+Maybe
713+~~~~~
714+
715+``Maybe`` describes an optional value. Either there is a value of the
716+given type, or there isn’t:
717+
718+.. code-block:: idris
719+
720+ data Maybe a = Just a | Nothing
721+
722+``Maybe`` is one way of giving a type to an operation that may
723+fail. For example, looking something up in a ``List`` (rather than a
724+vector) may result in an out of bounds error:
725+
726+.. code-block:: idris
727+
728+ list_lookup : Nat -> List a -> Maybe a
729+ list_lookup _ Nil = Nothing
730+ list_lookup Z (x :: xs) = Just x
731+ list_lookup (S k) (x :: xs) = list_lookup k xs
732+
733+The ``maybe`` function is used to process values of type ``Maybe``,
734+either by applying a function to the value, if there is one, or by
735+providing a default value:
736+
737+.. code-block:: idris
738+
739+ maybe : Lazy b -> (a -> b) -> Maybe a -> b
740+
741+Note that the type of the first argument is ``Lazy b`` rather than
742+simply ``b``. Since the default value might not be used, we mark it as
743+``Lazy`` in case it is a large expression where evaluating it then
744+discarding it would be wasteful.
745+
746+Tuples and Dependent Pairs
747+~~~~~~~~~~~~~~~~~~~~~~~~~~
748+
749+Values can be paired with the following built-in data type:
750+
751+.. code-block:: idris
752+
753+ data Pair a b = MkPair a b
754+
755+As syntactic sugar, we can write ``(a, b)`` which, according to
756+context, means either ``Pair a b`` or ``MkPair a b``. Tuples can
757+contain an arbitrary number of values, represented as nested pairs:
758+
759+.. code-block:: idris
760+
761+ fred : (String, Int)
762+ fred = ("Fred", 42)
763+
764+ jim : (String, Int, String)
765+ jim = ("Jim", 25, "Cambridge")
766+
767+Dependent Pairs
768+~~~~~~~~~~~~~~~
769+
770+Dependent pairs allow the type of the second element of a pair to depend
771+on the value of the first element. Traditionally, these are referred to
772+as “sigma types”:
773+
774+.. code-block:: idris
775+
776+ data Sigma : (A : Type) -> (P : A -> Type) -> Type where
777+ MkSigma : {P : A -> Type} -> (a : A) -> P a -> Sigma A P
778+
779+Again, there is syntactic sugar for this. ``(a : A ** P)`` is the type
780+of a pair of A and P, where the name ``a`` can occur inside ``P``.
781+``( a ** p )`` constructs a value of this type. For example, we can
782+pair a number with a ``Vect`` of a particular length.
783+
784+.. code-block:: idris
785+
786+ vec : (n : Nat ** Vect n Int)
787+ vec = (2 ** [3, 4])
788+
789+If you like, you can write it out the long way, the two are precisely
790+equivalent.
791+
792+.. code-block:: idris
793+
794+ vec : Sigma Nat (\n => Vect n Int)
795+ vec = MkSigma 2 [3, 4]
796+
797+The type checker could of course infer the value of the first element
798+from the length of the vector. We can write an underscore ``_`` in
799+place of values which we expect the type checker to fill in, so the
800+above definition could also be written as:
801+
802+.. code-block:: idris
803+
804+ vec : (n : Nat ** Vect n Int)
805+ vec = (_ ** [3, 4])
806+
807+We might also prefer to omit the type of the first element of the
808+pair, since, again, it can be inferred:
809+
810+.. code-block:: idris
811+
812+ vec : (n ** Vect n Int)
813+ vec = (_ ** [3, 4])
814+
815+One use for dependent pairs is to return values of dependent types
816+where the index is not necessarily known in advance. For example, if
817+we filter elements out of a ``Vect`` according to some predicate, we
818+will not know in advance what the length of the resulting vector will
819+be:
820+
821+.. code-block:: idris
822+
823+ filter : (a -> Bool) -> Vect n a -> (p ** Vect p a)
824+
825+If the ``Vect`` is empty, the result is easy:
826+
827+.. code-block:: idris
828+
829+ filter p Nil = (_ ** [])
830+
831+In the ``::`` case, we need to inspect the result of a recursive call
832+to ``filter`` to extract the length and the vector from the result. To
833+do this, we use ``with`` notation, which allows pattern matching on
834+intermediate values:
835+
836+.. code-block:: idris
837+
838+ filter p (x :: xs) with (filter p xs)
839+ | ( _ ** xs' ) = if (p x) then ( _ ** x :: xs' ) else ( _ ** xs' )
840+
841+We will see more on ``with`` notation later.
842+
843+.. _sect-more-expr:
844+
845+More Expressions
846+----------------
847+
848+``let`` bindings
849+~~~~~~~~~~~~~~~~
850+
851+Intermediate values can be calculated using ``let`` bindings:
852+
853+.. code-block:: idris
854+
855+ data Person = MkPerson String Int
856+
857+ showPerson : Person -> String
858+ showPerson p = let MkPerson name age = p in
859+ name ++ " is " ++ show age ++ " years old"
860+
861+ splitAt : Char -> String -> (String, String)
862+ splitAt c x = case break (== c) x of
863+ (x, y) => (x, strTail y)
864+
865+We can do simple pattern matching in ``let`` bindings too. For
866+example, we can extract fields from a record as follows, as well as by
867+pattern matching at the top level:
868+
869+.. code-block:: idris
870+
871+ data Person = MkPerson String Int
872+
873+ showPerson : Person -> String
874+ showPerson p = let MkPerson name age = p in
875+ name ++ " is " ++ show age ++ " years old"
876+
877+List comprehensions
878+~~~~~~~~~~~~~~~~~~~
879+
880+Idris provides *comprehension* notation as a convenient shorthand
881+for building lists. The general form is:
882+
883+::
884+
885+ [ expression | qualifiers ]
886+
887+This generates the list of values produced by evaluating the
888+``expression``, according to the conditions given by the comma
889+separated ``qualifiers``. For example, we can build a list of
890+Pythagorean triples as follows:
891+
892+.. code-block:: idris
893+
894+ pythag : Int -> List (Int, Int, Int)
895+ pythag n = [ (x, y, z) | z <- [1..n], y <- [1..z], x <- [1..y],
896+ x*x + y*y == z*z ]
897+
898+The ``[a..b]`` notation is another shorthand which builds a list of
899+numbers between ``a`` and ``b``. Alternatively ``[a,b..c]`` builds a
900+list of numbers between ``a`` and ``c`` with the increment specified
901+by the difference between ``a`` and ``b``. This works for any numeric
902+type, using the ``count`` function from the prelude.
903+
904+``case`` expressions
905+~~~~~~~~~~~~~~~~~~~~
906+
907+Another way of inspecting intermediate values of *simple* types is to
908+use a ``case`` expression. The following function, for example, splits
909+a string into two at a given character:
910+
911+.. code-block:: idris
912+
913+ splitAt : Char -> String -> (String, String)
914+ splitAt c x = case break (== c) x of
915+ (x, y) => (x, strTail y)
916+
917+``break`` is a library function which breaks a string into a pair of
918+strings at the point where the given function returns true. We then
919+deconstruct the pair it returns, and remove the first character of the
920+second string.
921+
922+A ``case`` expression can match several cases, for example, to inspect
923+an intermediate value of type ``Maybe a``. Recall ``list_lookup``
924+which looks up an index in a list, returning ``Nothing`` if the index
925+is out of bounds. We can use this to write ``lookup_default``, which
926+looks up an index and returns a default value if the index is out of
927+bounds:
928+
929+.. code-block:: idris
930+
931+ lookup_default : Nat -> List a -> a -> a
932+ lookup_default i xs def = case list_lookup i xs of
933+ Nothing => def
934+ Just x => x
935+
936+If the index is in bounds, we get the value at that index, otherwise
937+we get a default value:
938+
939+::
940+
941+ *usefultypes> lookup_default 2 [3,4,5,6] (-1)
942+ 5 : Integer
943+ *usefultypes> lookup_default 4 [3,4,5,6] (-1)
944+ -1 : Integer
945+
946+**Restrictions:** The ``case`` construct is intended for simple
947+analysis of intermediate expressions to avoid the need to write
948+auxiliary functions, and is also used internally to implement pattern
949+matching ``let`` and lambda bindings. It will *only* work if:
950+
951+- Each branch *matches* a value of the same type, and *returns* a
952+ value of the same type.
953+
954+- The type of the result is "known". i.e. the type of the expression
955+ can be determined *without* type checking the ``case``-expression
956+ itself.
957+
958+Dependent Records
959+-----------------
960+
961+*Records* are data types which collect several values (the record's
962+*fields*) together. Idris provides syntax for defining records and
963+*automatically generating field access and update functions. For
964+*example, we can represent a person's name and age in a record:
965+
966+.. code-block:: idris
967+
968+ record Person : Type where
969+ MkPerson : (name : String) ->
970+ (age : Int) -> Person
971+
972+ fred : Person
973+ fred = MkPerson "Fred" 30
974+
975+Record declarations are like ``data`` declarations, except that they
976+are introduced by the ``record`` keyword, and can only have one
977+constructor. The names of the binders in the constructor type
978+(``name`` and ``age``) here are the field names, which we can use to
979+access the field values:
980+
981+::
982+
983+ *record> name fred
984+ "Fred" : String
985+ *record> age fred
986+ 30 : Int
987+ *record> :t name
988+ name : Person -> String
989+
990+We can also use the field names to update a record (or, more
991+precisely, produce a new record with the given fields updated).
992+
993+.. code-block:: bash
994+
995+ *record> record { name = "Jim" } fred
996+ MkPerson "Jim" 30 : Person
997+ *record> record { name = "Jim", age = 20 } fred
998+ MkPerson "Jim" 20 : Person
999+
1000+The syntax ``record { field = val, ... }`` generates a function which
1001+updates the given fields in a record.
1002+
1003+Records, and fields within records, can have dependent types. Updates
1004+are allowed to change the type of a field, provided that the result is
1005+well-typed, and the result does not affect the type of the record as a
1006+whole. For example:
1007+
1008+.. code-block:: idris
1009+
1010+ record Class : Type where
1011+ ClassInfo : (students : Vect n Person) ->
1012+ (className : String) ->
1013+ Class
1014+
1015+It is safe to update the ``students`` field to a vector of a different
1016+length because it will not affect the type of the record:
1017+
1018+.. code-block:: idris
1019+
1020+ addStudent : Person -> Class -> Class
1021+ addStudent p c = record { students = p :: students c } c
1022+
1023+::
1024+
1025+ *record> addStudent fred (ClassInfo [] "CS")
1026+ ClassInfo (prelude.vect.:: (MkPerson "Fred" 30) (prelude.vect.Nil)) "CS"
1027+ : Class
1028+
1029+Nested record update
1030+~~~~~~~~~~~~~~~~~~~~
1031+
1032+Idris also provides a convenient syntax for accessing and updating
1033+nested records. For example, if a field is accessible with the
1034+expression ``c (b (a x))``, it can be updated using the following
1035+syntax:
1036+
1037+.. code-block:: idris
1038+
1039+ record { a->b->c = val } x
1040+
1041+This returns a new record, with the field accessed by the path
1042+``a->b->c`` set to ``x``. The syntax is first class, i.e. ``record {
1043+a->b->c = val }`` itself has a function type. Symmetrically, the field
1044+can also be accessed with the following syntax:
1045+
1046+.. code-block:: idris
1047+
1048+ record { a->b->c } x
docs/tutorial/views.rstnew file+98
@@ -0,0 +1,98 @@
1+.. _sec-views:
2+
3+=============================
4+Views and the “``with``” rule
5+=============================
6+
7+Dependent pattern matching
8+--------------------------
9+
10+Since types can depend on values, the form of some arguments can be
11+determined by the value of others. For example, if we were to write
12+down the implicit length arguments to ``(++)``, we’d see that the form
13+of the length argument was determined by whether the vector was empty
14+or not:
15+
16+.. code-block:: idris
17+
18+ (++) : Vect n a -> Vect m a -> Vect (n + m) a
19+ (++) {n=Z} [] ys = ys
20+ (++) {n=S k} (x :: xs) ys = x :: xs ++ ys
21+
22+If ``n`` was a successor in the ``[]`` case, or zero in the ``::``
23+case, the definition would not be well typed.
24+
25+.. _sect-nattobin:
26+
27+The ``with`` rule — matching intermediate values
28+------------------------------------------------
29+
30+Very often, we need to match on the result of an intermediate
31+computation. Idris provides a construct for this, the ``with``
32+rule, inspired by views in ``Epigram`` [1]_, which takes account of
33+the fact that matching on a value in a dependently typed language can
34+affect what we know about the forms of other values. In its simplest
35+form, the ``with`` rule adds another argument to the function being
36+defined, e.g. we have already seen a vector filter function, defined
37+as follows:
38+
39+.. code-block:: idris
40+
41+ filter : (a -> Bool) -> Vect n a -> (p ** Vect p a)
42+ filter p [] = ( _ ** [] )
43+ filter p (x :: xs) with (filter p xs)
44+ | ( _ ** xs' ) = if (p x) then ( _ ** x :: xs' ) else ( _ ** xs' )
45+
46+Here, the ``with`` clause allows us to deconstruct the result of
47+``filter p xs``. Effectively, it adds this value as an extra argument,
48+which we place after the vertical bar.
49+
50+If the intermediate computation itself has a dependent type, then the
51+result can affect the forms of other arguments — we can learn the form
52+of one value by testing another. For example, a ``Nat`` is either even
53+or odd. If it’s even it will be the sum of two equal ``Nat``.
54+Otherwise, it is the sum of two equal ``Nat`` plus one:
55+
56+.. code-block:: idris
57+
58+ data Parity : Nat -> Type where
59+ Even : Parity (n + n)
60+ Odd : Parity (S (n + n))
61+
62+We say ``Parity`` is a *view* of ``Nat``. It has a *covering function*
63+which tests whether it is even or odd and constructs the predicate
64+accordingly.
65+
66+.. code-block:: idris
67+
68+ parity : (n:Nat) -> Parity n
69+
70+We’ll come back to the definition of ``parity`` shortly. We can use it
71+to write a function which converts a natural number to a list of
72+binary digits (least significant first) as follows, using the ``with``
73+rule:
74+
75+.. code-block:: idris
76+
77+ natToBin : Nat -> List Bool
78+ natToBin Z = Nil
79+ natToBin k with (parity k)
80+ natToBin (j + j) | Even = False :: natToBin j
81+ natToBin (S (j + j)) | Odd = True :: natToBin j
82+
83+The value of the result of ``parity k`` affects the form of ``k``,
84+because the result of ``parity k`` depends on ``k``. So, as well as
85+the patterns for the result of the intermediate computation (``Even``
86+and ``odd``) right of the ``\mid``, we also write how the results
87+affect the other patterns left of the :math:`\mid`. Note that there is
88+a function in the patterns (``+``) and repeated occurrences of
89+``j``—this is allowed because another argument has determined the form
90+of these patterns.
91+
92+We will return to this function in Section :ref:`sect-provisional` to
93+complete the definition of ``parity``.
94+
95+.. [1] Conor McBride and James McKinna. 2004. The view from the
96+ left. J. Funct. Program. 14, 1 (January 2004),
97+ 69-111. DOI=10.1017/S0956796803004829
98+ http://dx.doi.org/10.1017/S0956796803004829ñ
idris.cabal+37−9
@@ -1,5 +1,5 @@
11Name: idris
2−Version: 0.9.16
2+Version: 0.9.17.1
33License: BSD3
44License-file: LICENSE
55Author: Edwin Brady
@@ -99,19 +99,25 @@ Extra-source-files:
9999 libs/base/base.ipkg
100100 libs/base/*.idr
101101 libs/base/Control/*.idr
102− libs/base/Control/Isomorphism/*.idr
103102 libs/base/Control/Monad/*.idr
104103 libs/base/Data/*.idr
105104 libs/base/Data/Vect/*.idr
106105 libs/base/Debug/*.idr
107− libs/base/Decidable/*.idr
108106 libs/base/Language/Reflection/*.idr
109107 libs/base/Makefile
110− libs/base/Network/*.idr
111108 libs/base/System/*.idr
112109 libs/base/System/Concurrency/*.idr
113110 libs/base/Syntax/*.idr
114111
112+ libs/contrib/contrib.ipkg
113+ libs/contrib/Makefile
114+ libs/contrib/Classes/*.idr
115+ libs/contrib/Control/*.idr
116+ libs/contrib/Control/Isomorphism/*.idr
117+ libs/contrib/Data/*.idr
118+ libs/contrib/Decidable/*.idr
119+ libs/contrib/Network/*.idr
120+ libs/contrib/System/Concurrency/*.idr
115121
116122 libs/effects/Makefile
117123 libs/effects/effects.ipkg
@@ -292,6 +298,12 @@ Extra-source-files:
292298 test/reg059/run
293299 test/reg059/*.idr
294300 test/reg059/expected
301+ test/reg060/run
302+ test/reg060/*.idr
303+ test/reg060/expected
304+ test/reg061/run
305+ test/reg061/*.idr
306+ test/reg061/expected
295307
296308 test/basic001/run
297309 test/basic001/*.idr
@@ -330,10 +342,9 @@ Extra-source-files:
330342 test/basic012/run
331343 test/basic012/*.idr
332344 test/basic012/expected
333−
334− test/buffer001-disabled/*.idr
335− test/buffer001-disabled/run
336− test/buffer001-disabled/expected
345+ test/basic013/run
346+ test/basic013/*.idr
347+ test/basic013/expected
337348
338349 test/delab001/*.idr
339350 test/delab001/run
@@ -504,9 +515,22 @@ Extra-source-files:
504515 test/proof004/run
505516 test/proof004/*.idr
506517 test/proof004/expected
518+ test/proof005/run
519+ test/proof005/*.idr
520+ test/proof005/expected
521+ test/proof006/run
522+ test/proof006/*.idr
523+ test/proof006/expected
524+ test/proof007/run
525+ test/proof007/*.idr
526+ test/proof007/expected
507527 test/proof008/run
508528 test/proof008/*.idr
509529 test/proof008/expected
530+ test/proof009/run
531+ test/proof009/*.idr
532+ test/proof009/expected
533+ test/proof009/input
510534
511535 test/quasiquote001/run
512536 test/quasiquote001/*.idr
@@ -622,7 +646,10 @@ Extra-source-files:
622646 test/docs002/input
623647 test/docs002/*.idr
624648 test/docs002/expected
625−
649+ test/docs003/run
650+ test/docs003/input
651+ test/docs003/*.idr
652+ test/docs003/expected
626653
627654
628655source-repository head
@@ -810,6 +837,7 @@ Library
810837 , vector-binary-instances < 0.3
811838 , xml < 1.4
812839 , zlib < 0.6
840+ , safe
813841 Extensions: MultiParamTypeClasses
814842 , DeriveFoldable
815843 , DeriveTraversable
libs/Makefile+10−5
@@ -1,28 +1,33 @@
11build:
22 $(MAKE) -C prelude build
33 $(MAKE) -C base build
4+ $(MAKE) -C contrib build
45 $(MAKE) -C effects build
56
67
78install:
89 $(MAKE) -C prelude install
910 $(MAKE) -C base install
11+ $(MAKE) -C contrib install
1012 $(MAKE) -C effects install
1113
1214clean:
1315 $(MAKE) -C prelude clean
1416 $(MAKE) -C base clean
17+ $(MAKE) -C contrib clean
1518 $(MAKE) -C effects clean
1619
1720doc:
18− $(MAKE) -C prelude doc
19− $(MAKE) -C base doc
20− $(MAKE) -C effects doc
21+ $(MAKE) -C prelude doc
22+ $(MAKE) -C base doc
23+ $(MAKE) -C contrib doc
24+ $(MAKE) -C effects doc
2125
2226doc_clean:
2327 $(MAKE) -C prelude doc_clean
24− $(MAKE) -C base doc_clean
25− $(MAKE) -C effects doc_clean
28+ $(MAKE) -C base doc_clean
29+ $(MAKE) -C contrib doc_clean
30+ $(MAKE) -C effects doc_clean
2631
2732
2833.PHONY: build install clean doc doc_clean
libs/base/Data/Buffer.idrdeleted−261
@@ -1,261 +0,0 @@
1−module Data.Buffer
2−
3−import Data.Fin
4−
5−%default total
6−
7−-- !!! TODO: Open issues:
8−-- 1. It may be theoretically nice to represent Buffer size as
9−-- Fin (2 ^ WORD_BITS) instead of Nat
10−-- 2. Primitives take Bits64 when really they should take the
11−-- equivalent of C's size_t (ideally unboxed)
12−-- 3. If we had access to host system information, we could reduce
13−-- the needed primitives by implementing the LE/BE variants on
14−-- top of the native variant plus a possible swab function
15−-- 4. Would be nice to be able to peek/append Int, Char, and Float,
16−-- all have fixed (though possibly implementation-dependent) widths.
17−-- Currently not in place due to lack of host system introspection.
18−-- 5. Would be nice to be able to peek/append the vector types, but
19−-- for now I'm only touching the C backend which AFAICT doesn't
20−-- support them.
21−-- 6. Conversion from Fin to Bits64 (which, re 2, should eventually
22−-- be a fixed-width implementation-dependent type) is likely
23−-- inefficient relative to conversion from Nat to Bits64
24−-- 7. We may want to have a separate type that is a product of Buffer
25−-- and offset rather than storing the offset in Buffer itself, which
26−-- would require exposing the offset argument of prim__appendBuffer
27−
28−||| A contiguous chunk of n bytes
29−abstract
30−record Buffer (n : Nat) where
31− constructor MkBuffer
32− offset : Nat
33− realBuffer : prim__UnsafeBuffer
34−
35−{-
36−record Buffer : Nat -> Type where
37− MkBuffer : ( offset : Nat ) -> ( realBuffer : prim__UnsafeBuffer ) -> Buffer n
38−-}
39−
40−bitsFromNat : Nat -> Bits64
41−bitsFromNat Z = 0
42−bitsFromNat (S k) = 1 + bitsFromNat k
43−
44−bitsFromFin : Fin n -> Bits64
45−bitsFromFin FZ = 0
46−bitsFromFin (FS k) = 1 + bitsFromFin k
47−
48−||| Allocate an empty Buffer. The size hint can be used to avoid
49−||| unnecessary reallocations and copies under the hood if the
50−||| approximate ultimate size of the Buffer is known. Users can assume
51−||| the new Buffer is word-aligned.
52−public
53−allocate : ( hint : Nat ) -> Buffer Z
54−allocate = MkBuffer Z . prim__allocate . bitsFromNat
55−
56−||| Append count repetitions of a Buffer to another Buffer
57−%assert_total
58−public
59−appendBuffer : Buffer n ->
60− ( count : Nat ) ->
61− Buffer m ->
62− Buffer ( n + count * m )
63−appendBuffer { n } { m } ( MkBuffer o1 r1 ) c ( MkBuffer o2 r2 ) =
64− MkBuffer o1 $ prim__appendBuffer r1 size1 count size2 off r2
65− where
66− size1 : Bits64
67− size1 = bitsFromNat ( n + o1 )
68− size2 : Bits64
69− size2 = bitsFromNat m
70− count : Bits64
71− count = bitsFromNat c
72− off : Bits64
73− off = bitsFromNat o2
74−
75−||| Copy a buffer, potentially allowing the (potentially large) space it
76−||| pointed to to be freed
77−public
78−copy : Buffer n -> Buffer n
79−copy { n } = replace ( plusZeroRightNeutral n ) . appendBuffer ( allocate n ) 1
80−
81−||| Create a view over a buffer
82−public
83−peekBuffer : { n : Nat } -> { offset : Nat } -> Buffer ( n + offset ) -> ( offset : Nat ) -> Buffer n
84−peekBuffer ( MkBuffer o r ) off = MkBuffer ( o + off ) r
85−
86−peekBits : ( prim__UnsafeBuffer -> Bits64 -> a ) ->
87− Buffer ( m + n ) ->
88− ( offset : Fin ( S n ) ) ->
89− a
90−peekBits prim ( MkBuffer o r ) = prim r . bitsFromNat . plus o . finToNat
91−
92−appendBits : ( prim__UnsafeBuffer ->
93− Bits64 ->
94− Bits64 ->
95− a ->
96− prim__UnsafeBuffer ) ->
97− Buffer n ->
98− ( count : Nat) ->
99− a ->
100− Buffer ( n + count * size )
101−appendBits { n } prim ( MkBuffer o r ) count =
102− MkBuffer o . prim r ( bitsFromNat $ n + o ) ( bitsFromNat count )
103−
104−
105−||| Read a Bits8 from a Buffer starting at offset
106−%assert_total
107−public
108−peekBits8 : Buffer ( 1 + n ) ->
109− ( offset : Fin ( S n ) ) ->
110− Bits8
111−peekBits8 = peekBits { m = 1 } prim__peekB8Native
112−
113−||| Append count repetitions of a Bits8 to a Buffer
114−%assert_total
115−public
116−appendBits8 : Buffer n ->
117− ( count : Nat ) ->
118− Bits8 ->
119− Buffer ( n + count * 1 )
120−appendBits8 = appendBits prim__appendB8Native
121−
122−||| Read a Bits16 in native byte order from a Buffer starting at offset
123−%assert_total
124−public
125−peekBits16Native : Buffer ( 2 + n ) ->
126− ( offset : Fin ( S n ) ) ->
127− Bits16
128−peekBits16Native = peekBits { m = 2 } prim__peekB16Native
129−
130−||| Read a little-endian Bits16 from a Buffer starting at offset
131−%assert_total
132−public
133−peekBits16LE : Buffer ( 2 + n ) -> ( offset : Fin ( S n ) ) -> Bits16
134−peekBits16LE = peekBits { m = 2 } prim__peekB16LE
135−
136−||| Read a big-endian Bits16 from a Buffer starting at offset
137−%assert_total
138−public
139−peekBits16BE : Buffer ( 2 + n ) -> ( offset : Fin ( S n ) ) -> Bits16
140−peekBits16BE = peekBits { m = 2 } prim__peekB16BE
141−
142−||| Append count repetitions of a Bits16 in native byte order to a Buffer
143−%assert_total
144−public
145−appendBits16Native : Buffer n ->
146− ( count : Nat ) ->
147− Bits16 ->
148− Buffer ( n + count * 2 )
149−appendBits16Native = appendBits prim__appendB16Native
150−
151−||| Append count repetitions of a little-endian Bits16 to a Buffer
152−%assert_total
153−public
154−appendBits16LE : Buffer n ->
155− ( count : Nat ) ->
156− Bits16 ->
157− Buffer ( n + count * 2 )
158−appendBits16LE = appendBits prim__appendB16LE
159−
160−||| Append count repetitions of a big-endian Bits16 to a Buffer
161−%assert_total
162−public
163−appendBits16BE : Buffer n ->
164− ( count : Nat ) ->
165− Bits16 ->
166− Buffer ( n + count * 2 )
167−appendBits16BE = appendBits prim__appendB16BE
168−
169−||| Read a Bits32 in native byte order from a Buffer starting at offset
170−%assert_total
171−public
172−peekBits32Native : Buffer ( 4 + n ) ->
173− ( offset : Fin ( S n ) ) ->
174− Bits32
175−peekBits32Native = peekBits { m = 4 } prim__peekB32Native
176−
177−||| Read a little-endian Bits32 from a Buffer starting at offset
178−%assert_total
179−public
180−peekBits32LE : Buffer ( 4 + n ) -> ( offset : Fin ( S n ) ) -> Bits32
181−peekBits32LE = peekBits { m = 4 } prim__peekB32LE
182−
183−||| Read a big-endian Bits32 from a Buffer starting at offset
184−%assert_total
185−public
186−peekBits32BE : Buffer ( 4 + n ) -> ( offset : Fin ( S n ) ) -> Bits32
187−peekBits32BE = peekBits { m = 4 } prim__peekB32BE
188−
189−||| Append count repetitions of a Bits32 in native byte order to a Buffer
190−%assert_total
191−public
192−appendBits32Native : Buffer n ->
193− ( count : Nat ) ->
194− Bits32 ->
195− Buffer ( n + count * 4 )
196−appendBits32Native = appendBits prim__appendB32Native
197−
198−||| Append count repetitions of a little-endian Bits32 to a Buffer
199−%assert_total
200−public
201−appendBits32LE : Buffer n ->
202− ( count : Nat ) ->
203− Bits32 ->
204− Buffer ( n + count * 4 )
205−appendBits32LE = appendBits prim__appendB32LE
206−
207−||| Append count repetitions of a big-endian Bits32 to a Buffer
208−%assert_total
209−public
210−appendBits32BE : Buffer n ->
211− ( count : Nat ) ->
212− Bits32 ->
213− Buffer ( n + count * 4 )
214−appendBits32BE = appendBits prim__appendB32BE
215−
216−||| Read a Bits64 in native byte order from a Buffer starting at offset
217−%assert_total
218−public
219−peekBits64Native : Buffer ( 8 + n ) ->
220− ( offset : Fin ( S n ) ) ->
221− Bits64
222−peekBits64Native = peekBits { m = 8 } prim__peekB64Native
223−
224−||| Read a little-endian Bits64 from a Buffer starting at offset
225−%assert_total
226−public
227−peekBits64LE : Buffer ( 8 + n ) -> ( offset : Fin ( S n ) ) -> Bits64
228−peekBits64LE = peekBits { m = 8 } prim__peekB64LE
229−
230−||| Read a big-endian Bits64 from a Buffer starting at offset
231−%assert_total
232−public
233−peekBits64BE : Buffer ( 8 + n ) -> ( offset : Fin ( S n ) ) -> Bits64
234−peekBits64BE = peekBits { m = 8 } prim__peekB64BE
235−
236−||| Append count repetitions of a Bits64 in native byte order to a Buffer
237−%assert_total
238−public
239−appendBits64Native : Buffer n ->
240− ( count : Nat ) ->
241− Bits64 ->
242− Buffer ( n + count * 8 )
243−appendBits64Native = appendBits prim__appendB64Native
244−
245−||| Append count repetitions of a little-endian Bits64 to a Buffer
246−%assert_total
247−public
248−appendBits64LE : Buffer n ->
249− ( count : Nat ) ->
250− Bits64 ->
251− Buffer ( n + count * 8 )
252−appendBits64LE = appendBits prim__appendB64LE
253−
254−||| Append count repetitions of a big-endian Bits64 to a Buffer
255−%assert_total
256−public
257−appendBits64BE : Buffer n ->
258− ( count : Nat ) ->
259− Bits64 ->
260− Buffer ( n + count * 8 )
261−appendBits64BE = appendBits prim__appendB64BE
libs/base/Language/Reflection/Utils.idr−15
@@ -93,15 +93,8 @@ instance Show Const where
9393 show (B16 b) = "(B16 ...)"
9494 show (B32 b) = "(B32 ...)"
9595 show (B64 b) = "(B64 ...)"
96− show (B8V xs) = "(B8V ...)"
97− show (B16V xs) = "(B16V ...)"
98− show (B32V xs) = "(B32V ...)"
99− show (B64V xs) = "(B64V ...)"
10096 show (AType x) = "(AType ...)"
10197 show StrType = "StrType"
102− show PtrType = "PtrType"
103− show ManagedPtrType = "ManagedPtrType"
104− show BufferType = "BufferType"
10598 show VoidType = "VoidType"
10699 show Forgot = "Forgot"
107100
@@ -117,7 +110,6 @@ instance Eq Reflection.IntTy where
117110 ITNative == ITNative = True
118111 ITBig == ITBig = True
119112 ITChar == ITChar = True
120− (ITVec x i) == (ITVec y j) = x == y && i == j
121113 _ == _ = False
122114
123115instance Eq ArithTy where
@@ -135,15 +127,8 @@ instance Eq Const where
135127 (B16 x) == (B16 y) = x == y
136128 (B32 x) == (B32 y) = x == y
137129 (B64 x) == (B64 y) = x == y
138− (B8V xs) == (B8V ys) = False -- TODO
139− (B16V xs) == (B16V ys) = False -- TODO
140− (B32V xs) == (B32V ys) = False -- TODO
141− (B64V xs) == (B64V ys) = False -- TODO
142130 (AType x) == (AType y) = x == y
143131 StrType == StrType = True
144− PtrType == PtrType = True
145− ManagedPtrType == ManagedPtrType = True
146− BufferType == BufferType = True
147132 VoidType == VoidType = True
148133 Forgot == Forgot = True
149134 _ == _ = False
libs/base/base.ipkg+7−14
@@ -3,15 +3,9 @@ package base
33opts = "--nobasepkgs --total -i ../prelude"
44modules = System,
55
6− Network.Cgi, Network.Socket,
76 Debug.Error, Debug.Trace,
87
98 System.Info,
10− System.Concurrency.Raw, System.Concurrency.Process,
11−
12− Decidable.Decidable, Decidable.Order,
13−
14− Providers,
159
1610 Language.Reflection.Utils,
1711
@@ -19,20 +13,19 @@ modules = System,
1913
2014 Data.Morphisms,
2115 Data.Bits, Data.Mod2,
22− Data.ZZ, Data.Sign,
23− Data.SortedMap, Data.SortedSet, Data.BoundedList,
24− Data.Fin, Data.Vect, Data.VectType,
16+ Data.Fin, Data.Vect, Data.VectType,
2517 Data.HVect, Data.Vect.Quantifiers,
26− Data.Floats, Data.Complex, Data.Heap, Data.Fun,
27− Data.Rel, Data.Buffer, Data.Erased,
28− Data.List, Data.Hash, Data.Matrix,
18+ Data.Floats, Data.Complex,
19+ Data.Erased, Data.List,
2920 Data.So,
3021
31− Control.Isomorphism, Control.Isomorphism.Primitives,
22+ Control.Isomorphism,
3223 Control.Monad.Identity,
3324 Control.Monad.RWS,
3425 Control.Monad.Trans,
3526 Control.Monad.State, Control.Monad.Writer, Control.Monad.Reader,
3627 Control.Category, Control.Arrow,
37− Control.Catchable, Control.IOExcept
28+ Control.Catchable, Control.IOExcept,
29+
30+ System.Concurrency.Raw
3831
libs/contrib/Classes/Verified.idrnew file+114
@@ -0,0 +1,114 @@
1+module Classes.Verified
2+
3+import Control.Algebra
4+
5+-- Due to these being basically unused and difficult to implement,
6+-- they're in contrib for a bit. Once a design is found that lets them
7+-- be implemented for a number of instances, and we get those
8+-- implementations, then some of them can move back to base (or even
9+-- prelude, in the cases of Functor, Applicative, Monad, Semigroup,
10+-- and Monoid).
11+
12+class Functor f => VerifiedFunctor (f : Type -> Type) where
13+ functorIdentity : {a : Type} -> (x : f a) -> map id x = id x
14+ functorComposition : {a : Type} -> {b : Type} -> (x : f a) ->
15+ (g1 : a -> b) -> (g2 : b -> c) ->
16+ map (g2 . g1) x = (map g2 . map g1) x
17+
18+
19+
20+class (Applicative f, VerifiedFunctor f) => VerifiedApplicative (f : Type -> Type) where
21+ applicativeMap : (x : f a) -> (g : a -> b) ->
22+ map g x = pure g <*> x
23+ applicativeIdentity : (x : f a) -> pure id <*> x = x
24+ applicativeComposition : (x : f a) -> (g1 : f (a -> b)) -> (g2 : f (b -> c)) ->
25+ ((pure (.) <*> g2) <*> g1) <*> x = g2 <*> (g1 <*> x)
26+ applicativeHomomorphism : (x : a) -> (g : a -> b) ->
27+ (<*>) {f} (pure g) (pure x) = pure {f} (g x)
28+ applicativeInterchange : (x : a) -> (g : f (a -> b)) ->
29+ g <*> pure x = pure (\g' : a -> b => g' x) <*> g
30+
31+
32+class (Monad m, VerifiedApplicative m) => VerifiedMonad (m : Type -> Type) where
33+ monadApplicative : (mf : m (a -> b)) -> (mx : m a) ->
34+ mf <*> mx = mf >>= \f =>
35+ mx >>= \x =>
36+ pure (f x)
37+ monadLeftIdentity : (x : a) -> (f : a -> m b) -> return x >>= f = f x
38+ monadRightIdentity : (mx : m a) -> mx >>= return = mx
39+ monadAssociativity : (mx : m a) -> (f : a -> m b) -> (g : b -> m c) ->
40+ (mx >>= f) >>= g = mx >>= (\x => f x >>= g)
41+
42+
43+class Semigroup a => VerifiedSemigroup a where
44+ total semigroupOpIsAssociative : (l, c, r : a) -> l <+> (c <+> r) = (l <+> c) <+> r
45+
46+instance VerifiedSemigroup (List a) where
47+ semigroupOpIsAssociative = appendAssociative
48+
49+--instance VerifiedSemigroup Nat where
50+-- semigroupOpIsAssociative = plusAssociative
51+
52+
53+class (VerifiedSemigroup a, Monoid a) => VerifiedMonoid a where
54+ total monoidNeutralIsNeutralL : (l : a) -> l <+> neutral = l
55+ total monoidNeutralIsNeutralR : (r : a) -> neutral <+> r = r
56+
57+-- instance VerifiedMonoid Nat where
58+-- monoidNeutralIsNeutralL = plusZeroRightNeutral
59+-- monoidNeutralIsNeutralR = plusZeroLeftNeutral
60+
61+instance VerifiedMonoid (List a) where
62+ monoidNeutralIsNeutralL = appendNilRightNeutral
63+ monoidNeutralIsNeutralR xs = Refl
64+
65+class (VerifiedMonoid a, Group a) => VerifiedGroup a where
66+ total groupInverseIsInverseL : (l : a) -> l <+> inverse l = neutral
67+ total groupInverseIsInverseR : (r : a) -> inverse r <+> r = neutral
68+
69+class (VerifiedGroup a, AbelianGroup a) => VerifiedAbelianGroup a where
70+ total abelianGroupOpIsCommutative : (l, r : a) -> l <+> r = r <+> l
71+
72+class (VerifiedAbelianGroup a, Ring a) => VerifiedRing a where
73+ total ringOpIsAssociative : (l, c, r : a) -> l <.> (c <.> r) = (l <.> c) <.> r
74+ total ringOpIsDistributiveL : (l, c, r : a) -> l <.> (c <+> r) = (l <.> c) <+> (l <.> r)
75+ total ringOpIsDistributiveR : (l, c, r : a) -> (l <+> c) <.> r = (l <.> r) <+> (c <.> r)
76+
77+class (VerifiedRing a, RingWithUnity a) => VerifiedRingWithUnity a where
78+ total ringWithUnityIsUnityL : (l : a) -> l <.> unity = l
79+ total ringWithUnityIsUnityR : (r : a) -> unity <.> r = r
80+
81+class JoinSemilattice a => VerifiedJoinSemilattice a where
82+ total joinSemilatticeJoinIsAssociative : (l, c, r : a) -> join l (join c r) = join (join l c) r
83+ total joinSemilatticeJoinIsCommutative : (l, r : a) -> join l r = join r l
84+ total joinSemilatticeJoinIsIdempotent : (e : a) -> join e e = e
85+
86+class MeetSemilattice a => VerifiedMeetSemilattice a where
87+ total meetSemilatticeMeetIsAssociative : (l, c, r : a) -> meet l (meet c r) = meet (meet l c) r
88+ total meetSemilatticeMeetIsCommutative : (l, r : a) -> meet l r = meet r l
89+ total meetSemilatticeMeetIsIdempotent : (e : a) -> meet e e = e
90+
91+class (VerifiedJoinSemilattice a, BoundedJoinSemilattice a) => VerifiedBoundedJoinSemilattice a where
92+ total boundedJoinSemilatticeBottomIsBottom : (e : a) -> join e bottom = e
93+
94+class (VerifiedMeetSemilattice a, BoundedMeetSemilattice a) => VerifiedBoundedMeetSemilattice a where
95+ total boundedMeetSemilatticeTopIsTop : (e : a) -> meet e top = e
96+
97+class (VerifiedJoinSemilattice a, VerifiedMeetSemilattice a) => VerifiedLattice a where
98+ total latticeMeetAbsorbsJoin : (l, r : a) -> meet l (join l r) = l
99+ total latticeJoinAbsorbsMeet : (l, r : a) -> join l (meet l r) = l
100+
101+class (VerifiedBoundedJoinSemilattice a, VerifiedBoundedMeetSemilattice a, VerifiedLattice a) => VerifiedBoundedLattice a where { }
102+
103+class (VerifiedRing a, Field a) => VerifiedField a where
104+ total fieldInverseIsInverseL : (l : a) -> l <.> inverseM l = unity
105+ total fieldInverseIsInverseR : (r : a) -> inverseM r <.> r = unity
106+
107+-- class (VerifiedRingWithUnity a, VerifiedAbelianGroup b, Module a b) => VerifiedModule a b where
108+-- total moduleScalarMultiplyComposition : (x,y : a) -> (v : b) -> x <#> (y <#> v) = (x <.> y) <#> v
109+-- total moduleScalarUnityIsUnity : (v : b) -> unity <#> v = v
110+-- total moduleScalarMultDistributiveWRTVectorAddition : (s : a) -> (v, w : b) -> s <#> (v <+> w) = (s <#> v) <+> (s <#> w)
111+-- total moduleScalarMultDistributiveWRTModuleAddition : (s, t : a) -> (v : b) -> (s <+> t) <#> v = (s <#> v) <+> (t <#> v)
112+
113+-- class (VerifiedField a, VerifiedModule a b) => VerifiedVectorSpace a b where {}
114+
libs/contrib/Control/Algebra.idrnew file+274
@@ -0,0 +1,274 @@
1+module Control.Algebra
2+
3+import Data.Heap
4+
5+-- XXX: change?
6+infixl 6 <->
7+infixl 6 <.>
8+infixl 5 <#>
9+
10+||| Sets equipped with a single binary operation that is associative, along with
11+||| a neutral element for that binary operation and inverses for all elements.
12+||| Must satisfy the following laws:
13+||| + Associativity of `<+>`:
14+||| forall a b c, a <+> (b <+> c) == (a <+> b) <+> c
15+||| + Neutral for `<+>`:
16+||| forall a, a <+> neutral == a
17+||| forall a, neutral <+> a == a
18+||| + Inverse for `<+>`:
19+||| forall a, a <+> inverse a == neutral
20+||| forall a, inverse a <+> a == neutral
21+class Monoid a => Group a where
22+ inverse : a -> a
23+
24+(<->) : Group a => a -> a -> a
25+(<->) left right = left <+> (inverse right)
26+
27+||| Sets equipped with a single binary operation that is associative and
28+||| commutative, along with a neutral element for that binary operation and
29+||| inverses for all elements. Must satisfy the following laws:
30+|||
31+||| + Associativity of `<+>`:
32+||| forall a b c, a <+> (b <+> c) == (a <+> b) <+> c
33+||| + Commutativity of `<+>`:
34+||| forall a b, a <+> b == b <+> a
35+||| + Neutral for `<+>`:
36+||| forall a, a <+> neutral == a
37+||| forall a, neutral <+> a == a
38+||| + Inverse for `<+>`:
39+||| forall a, a <+> inverse a == neutral
40+||| forall a, inverse a <+> a == neutral
41+class Group a => AbelianGroup a where { }
42+
43+
44+||| Sets equipped with two binary operations, one associative and commutative
45+||| supplied with a neutral element, and the other associative, with
46+||| distributivity laws relating the two operations. Must satisfy the following
47+||| laws:
48+|||
49+||| + Associativity of `<+>`:
50+||| forall a b c, a <+> (b <+> c) == (a <+> b) <+> c
51+||| + Commutativity of `<+>`:
52+||| forall a b, a <+> b == b <+> a
53+||| + Neutral for `<+>`:
54+||| forall a, a <+> neutral == a
55+||| forall a, neutral <+> a == a
56+||| + Inverse for `<+>`:
57+||| forall a, a <+> inverse a == neutral
58+||| forall a, inverse a <+> a == neutral
59+||| + Associativity of `<.>`:
60+||| forall a b c, a <.> (b <.> c) == (a <.> b) <.> c
61+||| + Distributivity of `<.>` and `<->`:
62+||| forall a b c, a <.> (b <+> c) == (a <.> b) <+> (a <.> c)
63+||| forall a b c, (a <+> b) <.> c == (a <.> c) <+> (b <.> c)
64+class AbelianGroup a => Ring a where
65+ (<.>) : a -> a -> a
66+
67+
68+||| Sets equipped with two binary operations, one associative and commutative
69+||| supplied with a neutral element, and the other associative supplied with a
70+||| neutral element, with distributivity laws relating the two operations. Must
71+||| satisfy the following laws:
72+|||
73+||| + Associativity of `<+>`:
74+||| forall a b c, a <+> (b <+> c) == (a <+> b) <+> c
75+||| + Commutativity of `<+>`:
76+||| forall a b, a <+> b == b <+> a
77+||| + Neutral for `<+>`:
78+||| forall a, a <+> neutral == a
79+||| forall a, neutral <+> a == a
80+||| + Inverse for `<+>`:
81+||| forall a, a <+> inverse a == neutral
82+||| forall a, inverse a <+> a == neutral
83+||| + Associativity of `<.>`:
84+||| forall a b c, a <.> (b <.> c) == (a <.> b) <.> c
85+||| + Neutral for `<.>`:
86+||| forall a, a <.> unity == a
87+||| forall a, unity <.> a == a
88+||| + Distributivity of `<.>` and `<->`:
89+||| forall a b c, a <.> (b <+> c) == (a <.> b) <+> (a <.> c)
90+||| forall a b c, (a <+> b) <.> c == (a <.> c) <+> (b <.> c)
91+class Ring a => RingWithUnity a where
92+ unity : a
93+
94+
95+||| Sets equipped with a binary operation that is commutative, associative and
96+||| idempotent. Must satisfy the following laws:
97+|||
98+||| + Associativity of join:
99+||| forall a b c, join a (join b c) == join (join a b) c
100+||| + Commutativity of join:
101+||| forall a b, join a b == join b a
102+||| + Idempotency of join:
103+||| forall a, join a a == a
104+|||
105+||| Join semilattices capture the notion of sets with a "least upper bound".
106+class JoinSemilattice a where
107+ join : a -> a -> a
108+
109+instance JoinSemilattice Nat where
110+ join = maximum
111+
112+instance Ord a => JoinSemilattice (MaxiphobicHeap a) where
113+ join = merge
114+
115+||| Sets equipped with a binary operation that is commutative, associative and
116+||| idempotent. Must satisfy the following laws:
117+|||
118+||| + Associativity of meet:
119+||| forall a b c, meet a (meet b c) == meet (meet a b) c
120+||| + Commutativity of meet:
121+||| forall a b, meet a b == meet b a
122+||| + Idempotency of meet:
123+||| forall a, meet a a == a
124+|||
125+||| Meet semilattices capture the notion of sets with a "greatest lower bound".
126+class MeetSemilattice a where
127+ meet : a -> a -> a
128+
129+instance MeetSemilattice Nat where
130+ meet = minimum
131+
132+
133+||| Sets equipped with a binary operation that is commutative, associative and
134+||| idempotent and supplied with a unitary element. Must satisfy the following
135+||| laws:
136+|||
137+||| + Associativity of join:
138+||| forall a b c, join a (join b c) == join (join a b) c
139+||| + Commutativity of join:
140+||| forall a b, join a b == join b a
141+||| + Idempotency of join:
142+||| forall a, join a a == a
143+||| + Bottom (Unitary Element):
144+||| forall a, join a bottom == a
145+|||
146+||| Join semilattices capture the notion of sets with a "least upper bound"
147+||| equipped with a "bottom" element.
148+class JoinSemilattice a => BoundedJoinSemilattice a where
149+ bottom : a
150+
151+
152+instance BoundedJoinSemilattice Nat where
153+ bottom = Z
154+
155+
156+||| Sets equipped with a binary operation that is commutative, associative and
157+||| idempotent and supplied with a unitary element. Must satisfy the following
158+||| laws:
159+|||
160+||| + Associativity of meet:
161+||| forall a b c, meet a (meet b c) == meet (meet a b) c
162+||| + Commutativity of meet:
163+||| forall a b, meet a b == meet b a
164+||| + Idempotency of meet:
165+||| forall a, meet a a == a
166+||| + Top (Unitary Element):
167+||| forall a, meet a top == a
168+|||
169+||| Meet semilattices capture the notion of sets with a "greatest lower bound"
170+||| equipped with a "top" element.
171+class MeetSemilattice a => BoundedMeetSemilattice a where
172+ top : a
173+
174+
175+
176+||| Sets equipped with two binary operations that are both commutative,
177+||| associative and idempotent, along with absorbtion laws for relating the two
178+||| binary operations. Must satisfy the following:
179+|||
180+||| + Associativity of meet and join:
181+||| forall a b c, meet a (meet b c) == meet (meet a b) c
182+||| forall a b c, join a (join b c) == join (join a b) c
183+||| + Commutativity of meet and join:
184+||| forall a b, meet a b == meet b a
185+||| forall a b, join a b == join b a
186+||| + Idempotency of meet and join:
187+||| forall a, meet a a == a
188+||| forall a, join a a == a
189+||| + Absorbtion laws for meet and join:
190+||| forall a b, meet a (join a b) == a
191+||| forall a b, join a (meet a b) == a
192+class (JoinSemilattice a, MeetSemilattice a) => Lattice a where { }
193+
194+
195+instance Lattice Nat where { }
196+
197+||| Sets equipped with two binary operations that are both commutative,
198+||| associative and idempotent and supplied with neutral elements, along with
199+||| absorbtion laws for relating the two binary operations. Must satisfy the
200+||| following:
201+|||
202+||| + Associativity of meet and join:
203+||| forall a b c, meet a (meet b c) == meet (meet a b) c
204+||| forall a b c, join a (join b c) == join (join a b) c
205+||| + Commutativity of meet and join:
206+||| forall a b, meet a b == meet b a
207+||| forall a b, join a b == join b a
208+||| + Idempotency of meet and join:
209+||| forall a, meet a a == a
210+||| forall a, join a a == a
211+||| + Absorbtion laws for meet and join:
212+||| forall a b, meet a (join a b) == a
213+||| forall a b, join a (meet a b) == a
214+||| + Neutral for meet and join:
215+||| forall a, meet a top == top
216+||| forall a, join a bottom == bottom
217+class (BoundedJoinSemilattice a, BoundedMeetSemilattice a) => BoundedLattice a where { }
218+
219+
220+-- Fields.
221+||| Sets equipped with two binary operations, both associative and commutative
222+||| supplied with a neutral element, with
223+||| distributivity laws relating the two operations. Must satisfy the following
224+||| laws:
225+|||
226+||| + Associativity of `<+>`:
227+||| forall a b c, a <+> (b <+> c) == (a <+> b) <+> c
228+||| + Commutativity of `<+>`:
229+||| forall a b, a <+> b == b <+> a
230+||| + Neutral for `<+>`:
231+||| forall a, a <+> neutral == a
232+||| forall a, neutral <+> a == a
233+||| + Inverse for `<+>`:
234+||| forall a, a <+> inverse a == neutral
235+||| forall a, inverse a <+> a == neutral
236+||| + Associativity of `<.>`:
237+||| forall a b c, a <.> (b <.> c) == (a <.> b) <.> c
238+||| + Unity for `<.>`:
239+||| forall a, a <.> unity == a
240+||| forall a, unity <.> a == a
241+||| + InverseM of `<.>`:
242+||| forall a, a <.> inverseM a == unity
243+||| forall a, inverseM a <.> a == unity
244+||| + Distributivity of `<.>` and `<->`:
245+||| forall a b c, a <.> (b <+> c) == (a <.> b) <+> (a <.> c)
246+||| forall a b c, (a <+> b) <.> c == (a <.> c) <+> (b <.> c)
247+class RingWithUnity a => Field a where
248+ inverseM : a -> a
249+
250+
251+||| A module over a ring is an additive abelian group of 'vectors' endowed with a
252+||| scale operation multiplying vectors by ring elements, and distributivity laws
253+||| relating the scale operation to both ring addition and module addition.
254+||| Must satisfy the following laws:
255+|||
256+||| + Compatibility of scalar multiplication with ring multiplication:
257+||| forall a b v, a <#> (b <#> v) = (a <.> b) <#> v
258+||| + Ring unity is the identity element of scalar multiplication:
259+||| forall v, unity <#> v = v
260+||| + Distributivity of `<#>` and `<+>`:
261+||| forall a v w, a <#> (v <+> w) == (a <#> v) <+> (a <#> w)
262+||| forall a b v, (a <+> b) <#> v == (a <#> v) <+> (b <#> v)
263+class (RingWithUnity a, AbelianGroup b) => Module a b where
264+ (<#>) : a -> b -> b
265+
266+
267+||| A vector space is a module over a ring that is also a field
268+class (Field a, Module a b) => VectorSpace a b where {}
269+
270+
271+-- XXX todo:
272+-- Structures where "abs" make sense.
273+-- Euclidean domains, etc.
274+-- Where to put fromInteger and fromRational?
libs/base/Control/Isomorphism/Primitives.idr → libs/contrib/Control/Isomorphism/Primitives.idrrenamed

The content is the same.

libs/base/Data/BoundedList.idr → libs/contrib/Data/BoundedList.idrrenamed

The content is the same.

libs/base/Data/Fun.idr → libs/contrib/Data/Fun.idrrenamed

The content is the same.

libs/contrib/Data/Graph.idrnew file+8
@@ -0,0 +1,8 @@
1+module Data.Graph
2+
3+import Data.Vect
4+
5+data Edge e = MkEdge e e
6+
7+data Graph : Nat −> Nat −> Type −> Type −> Type where
8+ MkGraph : Vect m v −> Vect n (Edge k) −> Graph m n v k
libs/base/Data/Hash.idr → libs/contrib/Data/Hash.idrrenamed

The content is the same.

libs/base/Data/Heap.idr → libs/contrib/Data/Heap.idrrenamed+1−3
@@ -5,6 +5,7 @@
55
66module Data.Heap
77
8+
89%default total
910%access public
1011
@@ -128,9 +129,6 @@ instance Ord a => Semigroup (MaxiphobicHeap a) where
128129instance Ord a => Monoid (MaxiphobicHeap a) where
129130 neutral = empty
130131
131−instance Ord a => JoinSemilattice (MaxiphobicHeap a) where
132− join = merge
133−
134132--------------------------------------------------------------------------------
135133-- Properties
136134--------------------------------------------------------------------------------
libs/base/Data/Matrix.idr → libs/contrib/Data/Matrix.idrrenamed+2−8
@@ -1,5 +1,7 @@
11module Data.Matrix
22
3+import Control.Algebra
4+
35import Data.Complex
46import Data.ZZ
57import Data.Fin
@@ -212,14 +214,6 @@ instance Semigroup Nat where
212214instance Monoid Nat where
213215 neutral = 0
214216
215−instance VerifiedSemigroup Nat where
216− semigroupOpIsAssociative = plusAssociative
217−
218−instance VerifiedMonoid Nat where
219− monoidNeutralIsNeutralL = plusZeroRightNeutral
220− monoidNeutralIsNeutralR = plusZeroLeftNeutral
221−
222−
223217instance Semigroup ZZ where
224218 (<+>) = (+)
225219
libs/contrib/Data/Polyhedra.idrnew file+9
@@ -0,0 +1,9 @@
1+module Data.Polyhedra
2+
3+import Data.Vect
4+import Data.Graph
5+
6+data Face f = MkFace (Vect n f)
7+
8+data Polyhedron : Nat -> Nat -> Nat -> Type -> Type where
9+ MkPolyhedron : Vect k v -> Vect m (Edge v) -> Vect n (Face v) -> Polyhedron k m n v
libs/base/Data/Rel.idr → libs/contrib/Data/Rel.idrrenamed

The content is the same.

libs/base/Data/Sign.idr → libs/contrib/Data/Sign.idrrenamed

The content is the same.

libs/base/Data/SortedMap.idr → libs/contrib/Data/SortedMap.idrrenamed

The content is the same.

libs/contrib/Data/SortedSet.idrnew file+28
@@ -0,0 +1,28 @@
1+module Data.SortedSet
2+
3+import Data.SortedMap
4+
5+-- TODO: add intersection, union, difference
6+
7+data SortedSet k = SetWrapper (Data.SortedMap.SortedMap k ())
8+
9+empty : SortedSet k
10+empty = SetWrapper Data.SortedMap.empty
11+
12+insert : Ord k => k -> SortedSet k -> SortedSet k
13+insert k (SetWrapper m) = SetWrapper (Data.SortedMap.insert k () m)
14+
15+delete : Ord k => k -> SortedSet k -> SortedSet k
16+delete k (SetWrapper m) = SetWrapper (Data.SortedMap.delete k m)
17+
18+contains : Ord k => k -> SortedSet k -> Bool
19+contains k (SetWrapper m) = isJust (Data.SortedMap.lookup k m)
20+
21+fromList : Ord k => List k -> SortedSet k
22+fromList l = SetWrapper (Data.SortedMap.fromList (map (\i => (i, ())) l))
23+
24+toList : SortedSet k -> List k
25+toList (SetWrapper m) = map (\(i, _) => i) (Data.SortedMap.toList m)
26+
27+instance Foldable SortedSet where
28+ foldr f e xs = foldr f e (Data.SortedSet.toList xs)
libs/base/Data/ZZ.idr → libs/contrib/Data/ZZ.idrrenamed

The content is the same.

libs/base/Decidable/Decidable.idr → libs/contrib/Decidable/Decidable.idrrenamed

The content is the same.

libs/base/Decidable/Order.idr → libs/contrib/Decidable/Order.idrrenamed

The content is the same.

libs/contrib/Makefilenew file+24
@@ -0,0 +1,24 @@
1+IDRIS := idris
2+PKG := contrib
3+
4+build:
5+ $(IDRIS) --build ${PKG}.ipkg
6+
7+install:
8+ $(IDRIS) --install ${PKG}.ipkg
9+
10+clean:
11+ $(IDRIS) --clean ${PKG}.ipkg
12+
13+rebuild: clean build
14+
15+doc:
16+ ${IDRIS} --mkdoc ${PKG}.ipkg
17+
18+doc_clean:
19+ rm -rf ${PKG}_doc
20+
21+linecount:
22+ find . -name '*.idr' | xargs wc -l
23+
24+.PHONY: build install clean rebuild linecount
libs/base/Network/Cgi.idr → libs/contrib/Network/Cgi.idrrenamed

The content is the same.

libs/base/Network/Socket.idr → libs/contrib/Network/Socket.idrrenamed

The content is the same.

libs/base/System/Concurrency/Process.idr → libs/contrib/System/Concurrency/Process.idrrenamed

The content is the same.

libs/contrib/contrib.ipkgnew file+18
@@ -0,0 +1,18 @@
1+package contrib
2+
3+opts = "--nobasepkgs --total -i ../prelude -i ../base"
4+modules = Control.Algebra,
5+ Control.Isomorphism.Primitives,
6+ Classes.Verified,
7+ Data.Fun, Data.Rel,
8+ Data.Hash, Data.Matrix,
9+ Data.ZZ, Data.Sign,
10+ Data.BoundedList,
11+ Data.Heap,
12+ Data.SortedMap, Data.SortedSet,
13+
14+ Decidable.Decidable, Decidable.Order,
15+
16+ Network.Cgi, Network.Socket,
17+
18+ System.Concurrency.Process
libs/effects/Effect/File.idr+4−3
@@ -117,9 +117,10 @@ FILE_IO t = MkEff t FileIO
117117||| @ m The file mode.
118118open : (fname : String)
119119 -> (m : Mode)
120− -> { [FILE_IO ()] ==> [FILE_IO (if result
121− then OpenFile m
122− else ())] } Eff Bool
120+ -> { [FILE_IO ()] ==> {result}
121+ [FILE_IO (if result
122+ then OpenFile m
123+ else ())] } Eff Bool
123124open f m = call $ Open f m
124125
125126
libs/prelude/Builtins.idr+25
@@ -149,3 +149,28 @@ believe_me x = prim__believe_me _ _ x
149149public %assert_total
150150really_believe_me : a -> b
151151really_believe_me x = prim__believe_me _ _ x
152+
153+-- Deprecated - for backward compatibility
154+Float : Type
155+Float = Double
156+
157+-- Pointers as external primitive; there's no literals for these, so no
158+-- need for them to be part of the compiler.
159+
160+abstract data Ptr : Type
161+abstract data ManagedPtr : Type
162+
163+%extern prim__readFile : prim__WorldType -> Ptr -> String
164+%extern prim__writeFile : prim__WorldType -> Ptr -> String -> Int
165+%extern prim__readString : prim__WorldType -> String
166+%extern prim__writeString : prim__WorldType -> String -> Int
167+
168+%extern prim__vm : Ptr
169+%extern prim__stdin : Ptr
170+%extern prim__stdout : Ptr
171+%extern prim__stderr : Ptr
172+
173+%extern prim__null : Ptr
174+%extern prim__registerPtr : Ptr -> Int -> ManagedPtr
175+
176+
libs/prelude/Decidable/Equality.idr−9
@@ -181,15 +181,6 @@ instance DecEq Integer where
181181 primitiveEq = believe_me (Refl {x})
182182 postulate primitiveNotEq : x = y -> Void
183183
184−--------------------------------------------------------------------------------
185−-- Float
186−--------------------------------------------------------------------------------
187−
188−instance DecEq Float where
189− decEq x y = if x == y then Yes primitiveEq else No primitiveNotEq
190− where primitiveEq : x = y
191− primitiveEq = believe_me (Refl {x})
192− postulate primitiveNotEq : x = y -> Void
193184
194185--------------------------------------------------------------------------------
195186-- String
libs/prelude/IO.idr+4−6
@@ -51,8 +51,10 @@ applyEnv : (env : FEnv ffi xs) ->
5151applyEnv [] f = f
5252applyEnv (x@(_, _) :: xs) f = applyEnv xs (f x)
5353
54−mkForeignPrim : ForeignPrimType xs env t
55−-- compiled as primitive
54+mkForeignPrim : {xs : _} -> {ffi : _} -> {env : FEnv ffi xs} -> {t : Type} ->
55+ ForeignPrimType xs env t
56+-- compiled as primitive. Compiler assumes argument order, so make it
57+-- explicit here.
5658
5759%inline
5860foreign_prim : (f : FFI) ->
@@ -134,10 +136,6 @@ data C_IntTypes : Type -> Type where
134136 C_IntBits16 : C_IntTypes Bits16
135137 C_IntBits32 : C_IntTypes Bits32
136138 C_IntBits64 : C_IntTypes Bits64
137− C_IntB8x16 : C_IntTypes Bits8x16
138− C_IntB16x8 : C_IntTypes Bits16x8
139− C_IntB32x4 : C_IntTypes Bits32x4
140− C_IntB64x2 : C_IntTypes Bits64x2
141139
142140-- Supported C foreign types
143141data C_Types : Type -> Type where
libs/prelude/Language/Reflection.idr+1−52
@@ -38,17 +38,14 @@ data TTUExp =
3838data NativeTy = IT8 | IT16 | IT32 | IT64
3939
4040data IntTy = ITFixed NativeTy | ITNative | ITBig | ITChar
41− | ITVec NativeTy Int
4241
4342data ArithTy = ATInt Language.Reflection.IntTy | ATFloat
4443
4544||| Primitive constants
4645data Const = I Int | BI Integer | Fl Float | Ch Char | Str String
4746 | B8 Bits8 | B16 Bits16 | B32 Bits32 | B64 Bits64
48− | B8V Bits8x16 | B16V Bits16x8
49− | B32V Bits32x4 | B64V Bits64x2
5047 | AType ArithTy | StrType
51− | PtrType | ManagedPtrType | BufferType | VoidType | Forgot
48+ | VoidType | Forgot
5249 | WorldType | TheWorld
5350%name Const c, c'
5451
@@ -361,38 +358,6 @@ instance Quotable Integer Raw where
361358 quotedTy = `(Integer)
362359 quote x = RConstant (BI x)
363360
364−instance Quotable Bits8x16 TT where
365− quotedTy = `(Bits8x16)
366− quote x = TConst (B8V x)
367−
368−instance Quotable Bits8x16 Raw where
369− quotedTy = `(Bits8x16)
370− quote x = RConstant (B8V x)
371−
372−instance Quotable Bits16x8 TT where
373− quotedTy = `(Bits16x8)
374− quote x = TConst (B16V x)
375−
376−instance Quotable Bits16x8 Raw where
377− quotedTy = `(Bits16x8)
378− quote x = RConstant (B16V x)
379−
380−instance Quotable Bits32x4 TT where
381− quotedTy = `(Bits32x4)
382− quote x = TConst (B32V x)
383−
384−instance Quotable Bits32x4 Raw where
385− quotedTy = `(Bits32x4)
386− quote x = RConstant (B32V x)
387−
388−instance Quotable Bits64x2 TT where
389− quotedTy = `(Bits64x2)
390− quote x = TConst (B64V x)
391−
392−instance Quotable Bits64x2 Raw where
393− quotedTy = `(Bits64x2)
394− quote x = RConstant (B64V x)
395−
396361instance Quotable String TT where
397362 quotedTy = `(String)
398363 quote x = TConst (Str x)
@@ -459,7 +424,6 @@ instance Quotable Reflection.IntTy TT where
459424 quote ITNative = `(Reflection.ITNative)
460425 quote ITBig = `(ITBig)
461426 quote ITChar = `(Reflection.ITChar)
462− quote (ITVec x y) = `(ITVec ~(quote x) ~(quote y))
463427
464428instance Quotable Reflection.IntTy Raw where
465429 quotedTy = `(Reflection.IntTy)
@@ -467,7 +431,6 @@ instance Quotable Reflection.IntTy Raw where
467431 quote ITNative = `(Reflection.ITNative)
468432 quote ITBig = `(ITBig)
469433 quote ITChar = `(Reflection.ITChar)
470− quote (ITVec x y) = `(ITVec ~(quote {t=Raw} x) ~(quote {t=Raw} y))
471434
472435instance Quotable ArithTy TT where
473436 quotedTy = `(ArithTy)
@@ -490,15 +453,8 @@ instance Quotable Const TT where
490453 quote (B16 x) = `(B16 ~(quote x))
491454 quote (B32 x) = `(B32 ~(quote x))
492455 quote (B64 x) = `(B64 ~(quote x))
493− quote (B8V xs) = `(B8V ~(quote xs))
494− quote (B16V xs) = `(B16V ~(quote xs))
495− quote (B32V xs) = `(B32V ~(quote xs))
496− quote (B64V xs) = `(B64V ~(quote xs))
497456 quote (AType x) = `(AType ~(quote x))
498457 quote StrType = `(StrType)
499− quote PtrType = `(PtrType)
500− quote ManagedPtrType = `(ManagedPtrType)
501− quote BufferType = `(BufferType)
502458 quote VoidType = `(VoidType)
503459 quote Forgot = `(Forgot)
504460 quote WorldType = `(WorldType)
@@ -515,15 +471,8 @@ instance Quotable Const Raw where
515471 quote (B16 x) = `(B16 ~(quote {t=Raw} x))
516472 quote (B32 x) = `(B32 ~(quote {t=Raw} x))
517473 quote (B64 x) = `(B64 ~(quote {t=Raw} x))
518− quote (B8V xs) = `(B8V ~(quote {t=Raw} xs))
519− quote (B16V xs) = `(B16V ~(quote {t=Raw} xs))
520− quote (B32V xs) = `(B32V ~(quote {t=Raw} xs))
521− quote (B64V xs) = `(B64V ~(quote {t=Raw} xs))
522474 quote (AType x) = `(AType ~(quote {t=Raw} x))
523475 quote StrType = `(StrType)
524− quote PtrType = `(PtrType)
525− quote ManagedPtrType = `(ManagedPtrType)
526− quote BufferType = `(BufferType)
527476 quote VoidType = `(VoidType)
528477 quote Forgot = `(Forgot)
529478 quote WorldType = `(WorldType)
libs/prelude/Prelude.idr+1−113
@@ -23,7 +23,7 @@ import public Prelude.Bits
2323import public Prelude.Uninhabited
2424import public Prelude.Pairs
2525import public Prelude.Stream
26−
26+import public Prelude.Providers
2727import public Decidable.Equality
2828import public Language.Reflection
2929import public Language.Reflection.Errors
@@ -115,106 +115,6 @@ instance Show Bits32 where
115115instance Show Bits64 where
116116 show b = b64ToString b
117117
118−%assert_total
119−viewB8x16 : Bits8x16 -> (Bits8, Bits8, Bits8, Bits8, Bits8, Bits8, Bits8, Bits8, Bits8, Bits8, Bits8, Bits8, Bits8, Bits8, Bits8, Bits8)
120−viewB8x16 x = ( prim__indexB8x16 x (prim__truncBigInt_B32 0)
121− , prim__indexB8x16 x (prim__truncBigInt_B32 1)
122− , prim__indexB8x16 x (prim__truncBigInt_B32 2)
123− , prim__indexB8x16 x (prim__truncBigInt_B32 3)
124− , prim__indexB8x16 x (prim__truncBigInt_B32 4)
125− , prim__indexB8x16 x (prim__truncBigInt_B32 5)
126− , prim__indexB8x16 x (prim__truncBigInt_B32 6)
127− , prim__indexB8x16 x (prim__truncBigInt_B32 7)
128− , prim__indexB8x16 x (prim__truncBigInt_B32 8)
129− , prim__indexB8x16 x (prim__truncBigInt_B32 9)
130− , prim__indexB8x16 x (prim__truncBigInt_B32 10)
131− , prim__indexB8x16 x (prim__truncBigInt_B32 11)
132− , prim__indexB8x16 x (prim__truncBigInt_B32 12)
133− , prim__indexB8x16 x (prim__truncBigInt_B32 13)
134− , prim__indexB8x16 x (prim__truncBigInt_B32 14)
135− , prim__indexB8x16 x (prim__truncBigInt_B32 15)
136− )
137−
138−instance Show Bits8x16 where
139− show x =
140− case viewB8x16 x of
141− (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) =>
142− "<" ++ prim__toStrB8 a
143− ++ ", " ++ prim__toStrB8 b
144− ++ ", " ++ prim__toStrB8 c
145− ++ ", " ++ prim__toStrB8 d
146− ++ ", " ++ prim__toStrB8 e
147− ++ ", " ++ prim__toStrB8 f
148− ++ ", " ++ prim__toStrB8 g
149− ++ ", " ++ prim__toStrB8 h
150− ++ ", " ++ prim__toStrB8 i
151− ++ ", " ++ prim__toStrB8 j
152− ++ ", " ++ prim__toStrB8 k
153− ++ ", " ++ prim__toStrB8 l
154− ++ ", " ++ prim__toStrB8 m
155− ++ ", " ++ prim__toStrB8 n
156− ++ ", " ++ prim__toStrB8 o
157− ++ ", " ++ prim__toStrB8 p
158− ++ ">"
159−
160−%assert_total
161−viewB16x8 : Bits16x8 -> (Bits16, Bits16, Bits16, Bits16, Bits16, Bits16, Bits16, Bits16)
162−viewB16x8 x = ( prim__indexB16x8 x (prim__truncBigInt_B32 0)
163− , prim__indexB16x8 x (prim__truncBigInt_B32 1)
164− , prim__indexB16x8 x (prim__truncBigInt_B32 2)
165− , prim__indexB16x8 x (prim__truncBigInt_B32 3)
166− , prim__indexB16x8 x (prim__truncBigInt_B32 4)
167− , prim__indexB16x8 x (prim__truncBigInt_B32 5)
168− , prim__indexB16x8 x (prim__truncBigInt_B32 6)
169− , prim__indexB16x8 x (prim__truncBigInt_B32 7)
170− )
171−
172−instance Show Bits16x8 where
173− show x =
174− case viewB16x8 x of
175− (a, b, c, d, e, f, g, h) =>
176− "<" ++ prim__toStrB16 a
177− ++ ", " ++ prim__toStrB16 b
178− ++ ", " ++ prim__toStrB16 c
179− ++ ", " ++ prim__toStrB16 d
180− ++ ", " ++ prim__toStrB16 e
181− ++ ", " ++ prim__toStrB16 f
182− ++ ", " ++ prim__toStrB16 g
183− ++ ", " ++ prim__toStrB16 h
184− ++ ">"
185−
186−%assert_total
187−viewB32x4 : Bits32x4 -> (Bits32, Bits32, Bits32, Bits32)
188−viewB32x4 x = ( prim__indexB32x4 x (prim__truncBigInt_B32 0)
189− , prim__indexB32x4 x (prim__truncBigInt_B32 1)
190− , prim__indexB32x4 x (prim__truncBigInt_B32 2)
191− , prim__indexB32x4 x (prim__truncBigInt_B32 3)
192− )
193−
194−instance Show Bits32x4 where
195− show x =
196− case viewB32x4 x of
197− (a, b, c, d) =>
198− "<" ++ prim__toStrB32 a
199− ++ ", " ++ prim__toStrB32 b
200− ++ ", " ++ prim__toStrB32 c
201− ++ ", " ++ prim__toStrB32 d
202− ++ ">"
203−
204−%assert_total
205−viewB64x2 : Bits64x2 -> (Bits64, Bits64)
206−viewB64x2 x = ( prim__indexB64x2 x (prim__truncBigInt_B32 0)
207− , prim__indexB64x2 x (prim__truncBigInt_B32 1)
208− )
209−
210−instance Show Bits64x2 where
211− show x =
212− case viewB64x2 x of
213− (a, b) =>
214− "<" ++ prim__toStrB64 a
215− ++ ", " ++ prim__toStrB64 b
216− ++ ">"
217−
218118instance (Show a, Show b) => Show (a, b) where
219119 show (x, y) = "(" ++ show x ++ ", " ++ show y ++ ")"
220120
@@ -419,18 +319,6 @@ curry f a b = f (a, b)
419319uncurry : (a -> b -> c) -> (a, b) -> c
420320uncurry f (a, b) = f a b
421321
422−uniformB8x16 : Bits8 -> Bits8x16
423−uniformB8x16 x = prim__mkB8x16 x x x x x x x x x x x x x x x x
424−
425−uniformB16x8 : Bits16 -> Bits16x8
426−uniformB16x8 x = prim__mkB16x8 x x x x x x x x
427−
428−uniformB32x4 : Bits32 -> Bits32x4
429−uniformB32x4 x = prim__mkB32x4 x x x x
430−
431−uniformB64x2 : Bits64 -> Bits64x2
432−uniformB64x2 x = prim__mkB64x2 x x
433−
434322---- some basic io
435323
436324||| Output a string to stdout without a trailing newline
libs/prelude/Prelude/Algebra.idr−294
@@ -22,8 +22,6 @@ infixl 5 <#>
2222class Semigroup a where
2323 (<+>) : a -> a -> a
2424
25−class Semigroup a => VerifiedSemigroup a where
26− total semigroupOpIsAssociative : (l, c, r : a) -> l <+> (c <+> r) = (l <+> c) <+> r
2725
2826||| Sets equipped with a single binary operation that is associative, along with
2927||| a neutral element for that binary operation. Must satisfy the following
@@ -37,295 +35,3 @@ class Semigroup a => VerifiedSemigroup a where
3735class Semigroup a => Monoid a where
3836 neutral : a
3937
40−class (VerifiedSemigroup a, Monoid a) => VerifiedMonoid a where
41− total monoidNeutralIsNeutralL : (l : a) -> l <+> neutral = l
42− total monoidNeutralIsNeutralR : (r : a) -> neutral <+> r = r
43−
44−||| Sets equipped with a single binary operation that is associative, along with
45−||| a neutral element for that binary operation and inverses for all elements.
46−||| Must satisfy the following laws:
47−||| + Associativity of `<+>`:
48−||| forall a b c, a <+> (b <+> c) == (a <+> b) <+> c
49−||| + Neutral for `<+>`:
50−||| forall a, a <+> neutral == a
51−||| forall a, neutral <+> a == a
52−||| + Inverse for `<+>`:
53−||| forall a, a <+> inverse a == neutral
54−||| forall a, inverse a <+> a == neutral
55−class Monoid a => Group a where
56− inverse : a -> a
57−
58−class (VerifiedMonoid a, Group a) => VerifiedGroup a where
59− total groupInverseIsInverseL : (l : a) -> l <+> inverse l = neutral
60− total groupInverseIsInverseR : (r : a) -> inverse r <+> r = neutral
61−
62−(<->) : Group a => a -> a -> a
63−(<->) left right = left <+> (inverse right)
64−
65−||| Sets equipped with a single binary operation that is associative and
66−||| commutative, along with a neutral element for that binary operation and
67−||| inverses for all elements. Must satisfy the following laws:
68−|||
69−||| + Associativity of `<+>`:
70−||| forall a b c, a <+> (b <+> c) == (a <+> b) <+> c
71−||| + Commutativity of `<+>`:
72−||| forall a b, a <+> b == b <+> a
73−||| + Neutral for `<+>`:
74−||| forall a, a <+> neutral == a
75−||| forall a, neutral <+> a == a
76−||| + Inverse for `<+>`:
77−||| forall a, a <+> inverse a == neutral
78−||| forall a, inverse a <+> a == neutral
79−class Group a => AbelianGroup a where { }
80−
81−class (VerifiedGroup a, AbelianGroup a) => VerifiedAbelianGroup a where
82− total abelianGroupOpIsCommutative : (l, r : a) -> l <+> r = r <+> l
83−
84−||| Sets equipped with two binary operations, one associative and commutative
85−||| supplied with a neutral element, and the other associative, with
86−||| distributivity laws relating the two operations. Must satisfy the following
87−||| laws:
88−|||
89−||| + Associativity of `<+>`:
90−||| forall a b c, a <+> (b <+> c) == (a <+> b) <+> c
91−||| + Commutativity of `<+>`:
92−||| forall a b, a <+> b == b <+> a
93−||| + Neutral for `<+>`:
94−||| forall a, a <+> neutral == a
95−||| forall a, neutral <+> a == a
96−||| + Inverse for `<+>`:
97−||| forall a, a <+> inverse a == neutral
98−||| forall a, inverse a <+> a == neutral
99−||| + Associativity of `<.>`:
100−||| forall a b c, a <.> (b <.> c) == (a <.> b) <.> c
101−||| + Distributivity of `<.>` and `<->`:
102−||| forall a b c, a <.> (b <+> c) == (a <.> b) <+> (a <.> c)
103−||| forall a b c, (a <+> b) <.> c == (a <.> c) <+> (b <.> c)
104−class AbelianGroup a => Ring a where
105− (<.>) : a -> a -> a
106−
107−class (VerifiedAbelianGroup a, Ring a) => VerifiedRing a where
108− total ringOpIsAssociative : (l, c, r : a) -> l <.> (c <.> r) = (l <.> c) <.> r
109− total ringOpIsDistributiveL : (l, c, r : a) -> l <.> (c <+> r) = (l <.> c) <+> (l <.> r)
110− total ringOpIsDistributiveR : (l, c, r : a) -> (l <+> c) <.> r = (l <.> r) <+> (c <.> r)
111−
112−||| Sets equipped with two binary operations, one associative and commutative
113−||| supplied with a neutral element, and the other associative supplied with a
114−||| neutral element, with distributivity laws relating the two operations. Must
115−||| satisfy the following laws:
116−|||
117−||| + Associativity of `<+>`:
118−||| forall a b c, a <+> (b <+> c) == (a <+> b) <+> c
119−||| + Commutativity of `<+>`:
120−||| forall a b, a <+> b == b <+> a
121−||| + Neutral for `<+>`:
122−||| forall a, a <+> neutral == a
123−||| forall a, neutral <+> a == a
124−||| + Inverse for `<+>`:
125−||| forall a, a <+> inverse a == neutral
126−||| forall a, inverse a <+> a == neutral
127−||| + Associativity of `<.>`:
128−||| forall a b c, a <.> (b <.> c) == (a <.> b) <.> c
129−||| + Neutral for `<.>`:
130−||| forall a, a <.> unity == a
131−||| forall a, unity <.> a == a
132−||| + Distributivity of `<.>` and `<->`:
133−||| forall a b c, a <.> (b <+> c) == (a <.> b) <+> (a <.> c)
134−||| forall a b c, (a <+> b) <.> c == (a <.> c) <+> (b <.> c)
135−class Ring a => RingWithUnity a where
136− unity : a
137−
138−class (VerifiedRing a, RingWithUnity a) => VerifiedRingWithUnity a where
139− total ringWithUnityIsUnityL : (l : a) -> l <.> unity = l
140− total ringWithUnityIsUnityR : (r : a) -> unity <.> r = r
141−
142−||| Sets equipped with a binary operation that is commutative, associative and
143−||| idempotent. Must satisfy the following laws:
144−|||
145−||| + Associativity of join:
146−||| forall a b c, join a (join b c) == join (join a b) c
147−||| + Commutativity of join:
148−||| forall a b, join a b == join b a
149−||| + Idempotency of join:
150−||| forall a, join a a == a
151−|||
152−||| Join semilattices capture the notion of sets with a "least upper bound".
153−class JoinSemilattice a where
154− join : a -> a -> a
155−
156−class JoinSemilattice a => VerifiedJoinSemilattice a where
157− total joinSemilatticeJoinIsAssociative : (l, c, r : a) -> join l (join c r) = join (join l c) r
158− total joinSemilatticeJoinIsCommutative : (l, r : a) -> join l r = join r l
159− total joinSemilatticeJoinIsIdempotent : (e : a) -> join e e = e
160−
161−||| Sets equipped with a binary operation that is commutative, associative and
162−||| idempotent. Must satisfy the following laws:
163−|||
164−||| + Associativity of meet:
165−||| forall a b c, meet a (meet b c) == meet (meet a b) c
166−||| + Commutativity of meet:
167−||| forall a b, meet a b == meet b a
168−||| + Idempotency of meet:
169−||| forall a, meet a a == a
170−|||
171−||| Meet semilattices capture the notion of sets with a "greatest lower bound".
172−class MeetSemilattice a where
173− meet : a -> a -> a
174−
175−class MeetSemilattice a => VerifiedMeetSemilattice a where
176− total meetSemilatticeMeetIsAssociative : (l, c, r : a) -> meet l (meet c r) = meet (meet l c) r
177− total meetSemilatticeMeetIsCommutative : (l, r : a) -> meet l r = meet r l
178− total meetSemilatticeMeetIsIdempotent : (e : a) -> meet e e = e
179−
180−||| Sets equipped with a binary operation that is commutative, associative and
181−||| idempotent and supplied with a unitary element. Must satisfy the following
182−||| laws:
183−|||
184−||| + Associativity of join:
185−||| forall a b c, join a (join b c) == join (join a b) c
186−||| + Commutativity of join:
187−||| forall a b, join a b == join b a
188−||| + Idempotency of join:
189−||| forall a, join a a == a
190−||| + Bottom (Unitary Element):
191−||| forall a, join a bottom == a
192−|||
193−||| Join semilattices capture the notion of sets with a "least upper bound"
194−||| equipped with a "bottom" element.
195−class JoinSemilattice a => BoundedJoinSemilattice a where
196− bottom : a
197−
198−class (VerifiedJoinSemilattice a, BoundedJoinSemilattice a) => VerifiedBoundedJoinSemilattice a where
199− total boundedJoinSemilatticeBottomIsBottom : (e : a) -> join e bottom = e
200−
201−||| Sets equipped with a binary operation that is commutative, associative and
202−||| idempotent and supplied with a unitary element. Must satisfy the following
203−||| laws:
204−|||
205−||| + Associativity of meet:
206−||| forall a b c, meet a (meet b c) == meet (meet a b) c
207−||| + Commutativity of meet:
208−||| forall a b, meet a b == meet b a
209−||| + Idempotency of meet:
210−||| forall a, meet a a == a
211−||| + Top (Unitary Element):
212−||| forall a, meet a top == a
213−|||
214−||| Meet semilattices capture the notion of sets with a "greatest lower bound"
215−||| equipped with a "top" element.
216−class MeetSemilattice a => BoundedMeetSemilattice a where
217− top : a
218−
219−class (VerifiedMeetSemilattice a, BoundedMeetSemilattice a) => VerifiedBoundedMeetSemilattice a where
220− total boundedMeetSemilatticeTopIsTop : (e : a) -> meet e top = e
221−
222−||| Sets equipped with two binary operations that are both commutative,
223−||| associative and idempotent, along with absorbtion laws for relating the two
224−||| binary operations. Must satisfy the following:
225−|||
226−||| + Associativity of meet and join:
227−||| forall a b c, meet a (meet b c) == meet (meet a b) c
228−||| forall a b c, join a (join b c) == join (join a b) c
229−||| + Commutativity of meet and join:
230−||| forall a b, meet a b == meet b a
231−||| forall a b, join a b == join b a
232−||| + Idempotency of meet and join:
233−||| forall a, meet a a == a
234−||| forall a, join a a == a
235−||| + Absorbtion laws for meet and join:
236−||| forall a b, meet a (join a b) == a
237−||| forall a b, join a (meet a b) == a
238−class (JoinSemilattice a, MeetSemilattice a) => Lattice a where { }
239−
240−class (VerifiedJoinSemilattice a, VerifiedMeetSemilattice a) => VerifiedLattice a where
241− total latticeMeetAbsorbsJoin : (l, r : a) -> meet l (join l r) = l
242− total latticeJoinAbsorbsMeet : (l, r : a) -> join l (meet l r) = l
243−
244−||| Sets equipped with two binary operations that are both commutative,
245−||| associative and idempotent and supplied with neutral elements, along with
246−||| absorbtion laws for relating the two binary operations. Must satisfy the
247−||| following:
248−|||
249−||| + Associativity of meet and join:
250−||| forall a b c, meet a (meet b c) == meet (meet a b) c
251−||| forall a b c, join a (join b c) == join (join a b) c
252−||| + Commutativity of meet and join:
253−||| forall a b, meet a b == meet b a
254−||| forall a b, join a b == join b a
255−||| + Idempotency of meet and join:
256−||| forall a, meet a a == a
257−||| forall a, join a a == a
258−||| + Absorbtion laws for meet and join:
259−||| forall a b, meet a (join a b) == a
260−||| forall a b, join a (meet a b) == a
261−||| + Neutral for meet and join:
262−||| forall a, meet a top == top
263−||| forall a, join a bottom == bottom
264−class (BoundedJoinSemilattice a, BoundedMeetSemilattice a) => BoundedLattice a where { }
265−
266−class (VerifiedBoundedJoinSemilattice a, VerifiedBoundedMeetSemilattice a, VerifiedLattice a) => VerifiedBoundedLattice a where { }
267−
268−-- Fields.
269−||| Sets equipped with two binary operations, both associative and commutative
270−||| supplied with a neutral element, with
271−||| distributivity laws relating the two operations. Must satisfy the following
272−||| laws:
273−|||
274−||| + Associativity of `<+>`:
275−||| forall a b c, a <+> (b <+> c) == (a <+> b) <+> c
276−||| + Commutativity of `<+>`:
277−||| forall a b, a <+> b == b <+> a
278−||| + Neutral for `<+>`:
279−||| forall a, a <+> neutral == a
280−||| forall a, neutral <+> a == a
281−||| + Inverse for `<+>`:
282−||| forall a, a <+> inverse a == neutral
283−||| forall a, inverse a <+> a == neutral
284−||| + Associativity of `<.>`:
285−||| forall a b c, a <.> (b <.> c) == (a <.> b) <.> c
286−||| + Unity for `<.>`:
287−||| forall a, a <.> unity == a
288−||| forall a, unity <.> a == a
289−||| + InverseM of `<.>`:
290−||| forall a, a <.> inverseM a == unity
291−||| forall a, inverseM a <.> a == unity
292−||| + Distributivity of `<.>` and `<->`:
293−||| forall a b c, a <.> (b <+> c) == (a <.> b) <+> (a <.> c)
294−||| forall a b c, (a <+> b) <.> c == (a <.> c) <+> (b <.> c)
295−class RingWithUnity a => Field a where
296− inverseM : a -> a
297−
298−class (VerifiedRing a, Field a) => VerifiedField a where
299− total fieldInverseIsInverseL : (l : a) -> l <.> inverseM l = unity
300− total fieldInverseIsInverseR : (r : a) -> inverseM r <.> r = unity
301−
302−||| A module over a ring is an additive abelian group of 'vectors' endowed with a
303−||| scale operation multiplying vectors by ring elements, and distributivity laws
304−||| relating the scale operation to both ring addition and module addition.
305−||| Must satisfy the following laws:
306−|||
307−||| + Compatibility of scalar multiplication with ring multiplication:
308−||| forall a b v, a <#> (b <#> v) = (a <.> b) <#> v
309−||| + Ring unity is the identity element of scalar multiplication:
310−||| forall v, unity <#> v = v
311−||| + Distributivity of `<#>` and `<+>`:
312−||| forall a v w, a <#> (v <+> w) == (a <#> v) <+> (a <#> w)
313−||| forall a b v, (a <+> b) <#> v == (a <#> v) <+> (b <#> v)
314−class (RingWithUnity a, AbelianGroup b) => Module a b where
315− (<#>) : a -> b -> b
316−
317−class (VerifiedRingWithUnity a, VerifiedAbelianGroup b, Module a b) => VerifiedModule a b where
318− total moduleScalarMultiplyComposition : (x,y : a) -> (v : b) -> x <#> (y <#> v) = (x <.> y) <#> v
319− total moduleScalarUnityIsUnity : (v : b) -> unity {a} <#> v = v
320− total moduleScalarMultDistributiveWRTVectorAddition : (s : a) -> (v, w : b) -> s <#> (v <+> w) = (s <#> v) <+> (s <#> w)
321− total moduleScalarMultDistributiveWRTModuleAddition : (s, t : a) -> (v : b) -> (s <+> t) <#> v = (s <#> v) <+> (t <#> v)
322−
323−||| A vector space is a module over a ring that is also a field
324−class (Field a, Module a b) => VectorSpace a b where {}
325−
326−class (VerifiedField a, VerifiedModule a b) => VerifiedVectorSpace a b where {}
327−
328−-- XXX todo:
329−-- Structures where "abs" make sense.
330−-- Euclidean domains, etc.
331−-- Where to put fromInteger and fromRational?
libs/prelude/Prelude/Applicative.idr−11
@@ -15,17 +15,6 @@ class Functor f => Applicative (f : Type -> Type) where
1515 pure : a -> f a
1616 (<*>) : f (a -> b) -> f a -> f b
1717
18−class (Applicative f, VerifiedFunctor f) => VerifiedApplicative (f : Type -> Type) where
19− applicativeMap : (x : f a) -> (g : a -> b) ->
20− map g x = pure g <*> x
21− applicativeIdentity : (x : f a) -> pure id <*> x = x
22− applicativeComposition : (x : f a) -> (g1 : f (a -> b)) -> (g2 : f (b -> c)) ->
23− ((pure (.) <*> g2) <*> g1) <*> x = g2 <*> (g1 <*> x)
24− applicativeHomomorphism : (x : a) -> (g : a -> b) ->
25− (<*>) {f} (pure g) (pure x) = pure {f} (g x)
26− applicativeInterchange : (x : a) -> (g : f (a -> b)) ->
27− g <*> pure x = pure (\g' : a -> b => g' x) <*> g
28−
2918infixl 2 <*
3019(<*) : Applicative f => f a -> f b -> f a
3120a <* b = map const a <*> b
libs/prelude/Prelude/Cast.idr+2
@@ -1,5 +1,7 @@
11module Prelude.Cast
22
3+import public Builtins
4+
35||| Type class for transforming a instance of a data type to another type.
46class Cast from to where
57 ||| Perform a cast operation.
libs/prelude/Prelude/Functor.idr−6
@@ -18,9 +18,3 @@ infixl 4 <$>
1818(<$>) : Functor f => (m : a -> b) -> f a -> f b
1919m <$> x = map m x
2020
21−class Functor f => VerifiedFunctor (f : Type -> Type) where
22− functorIdentity : {a : Type} -> (x : f a) -> map id x = id x
23− functorComposition : {a : Type} -> {b : Type} -> (x : f a) ->
24− (g1 : a -> b) -> (g2 : b -> c) ->
25− map (g2 . g1) x = (map g2 . map g1) x
26−
libs/prelude/Prelude/List.idr−6
@@ -809,12 +809,6 @@ hasAnyByNilFalse p (x::xs) =
809809hasAnyNilFalse : Eq a => (l : List a) -> hasAny [] l = False
810810hasAnyNilFalse l = ?hasAnyNilFalseBody
811811
812−instance VerifiedSemigroup (List a) where
813− semigroupOpIsAssociative = appendAssociative
814−
815−instance VerifiedMonoid (List a) where
816− monoidNeutralIsNeutralL = appendNilRightNeutral
817− monoidNeutralIsNeutralR xs = Refl
818812
819813--------------------------------------------------------------------------------
820814-- Proofs
libs/prelude/Prelude/Monad.idr−10
@@ -14,16 +14,6 @@ infixl 5 >>=
1414class Applicative m => Monad (m : Type -> Type) where
1515 (>>=) : m a -> (a -> m b) -> m b
1616
17−class (Monad m, VerifiedApplicative m) => VerifiedMonad (m : Type -> Type) where
18− monadApplicative : (mf : m (a -> b)) -> (mx : m a) ->
19− mf <*> mx = mf >>= \f =>
20− mx >>= \x =>
21− pure (f x)
22− monadLeftIdentity : (x : a) -> (f : a -> m b) -> return x >>= f = f x
23− monadRightIdentity : (mx : m a) -> mx >>= return = mx
24− monadAssociativity : (mx : m a) -> (f : a -> m b) -> (g : b -> m c) ->
25− (mx >>= f) >>= g = mx >>= (\x => f x >>= g)
26−
2717||| Also called `join` or mu
2818flatten : Monad m => m (m a) -> m a
2919flatten a = a >>= id
libs/prelude/Prelude/Nat.idr−12
@@ -243,18 +243,6 @@ instance Monoid Multiplicative where
243243instance Monoid Additive where
244244 neutral = getAdditive Z
245245
246−instance MeetSemilattice Nat where
247− meet = minimum
248−
249−instance JoinSemilattice Nat where
250− join = maximum
251−
252−instance Lattice Nat where { }
253−
254−instance BoundedJoinSemilattice Nat where
255− bottom = Z
256−
257−
258246||| Casts negative `Ints` to 0.
259247instance Cast Int Nat where
260248 cast i = fromInteger (cast i)
libs/base/Providers.idr → libs/prelude/Prelude/Providers.idrrenamed+5−1
@@ -1,4 +1,8 @@
1−module Providers
1+module Prelude.Providers
2+
3+import Prelude.Functor
4+import Prelude.Applicative
5+import Prelude.Monad
26
37||| Type providers must build one of these in an IO computation.
48public
libs/prelude/prelude.ipkg+1−1
@@ -8,7 +8,7 @@ modules = Builtins, Prelude, IO,
88 Prelude.Maybe, Prelude.Monad, Prelude.Applicative, Prelude.Either,
99 Prelude.Strings, Prelude.Chars, Prelude.Functor,
1010 Prelude.Foldable, Prelude.Traversable, Prelude.Bits, Prelude.Stream,
11− Prelude.Uninhabited, Prelude.Pairs,
11+ Prelude.Uninhabited, Prelude.Pairs, Prelude.Providers,
1212
1313 Language.Reflection, Language.Reflection.Errors, Language.Reflection.Tactical,
1414
mkpkg.sh+9
@@ -10,6 +10,15 @@ git tag v$VERSION -a
1010
1111cabal sdist
1212
13+# Generate Idris library docs and put them in lib_docs.tar.gz in the root
14+make lib_doc
15+DOCDIR=`mktemp -d /tmp/docsXXXXX`
16+cp -r libs/base/base_doc "$DOCDIR"
17+cp -r libs/prelude/prelude_doc "$DOCDIR"
18+cp -r libs/effects/effects_doc "$DOCDIR"
19+cp -r libs/contrib/contrib_doc "$DOCDIR"
20+tar -czvf lib_docs.tar.gz -C "$DOCDIR" prelude_doc base_doc effects_doc contrib_doc
21+
1322cabal configure --prefix=/usr/local
1423cabal build
1524cabal copy --destdir=/tmp/idris-pkg/
rts/Makefile+3−2
@@ -1,9 +1,10 @@
11include ../config.mk
22
33OBJS = idris_rts.o idris_heap.o idris_gc.o idris_gmp.o idris_bitstring.o \
4− idris_opts.o idris_stats.o mini-gmp.o
4+ idris_opts.o idris_stats.o idris_utf8.o mini-gmp.o
55HDRS = idris_rts.h idris_heap.h idris_gc.h idris_gmp.h idris_bitstring.h \
6− idris_opts.h idris_stats.h mini-gmp.h idris_stdfgn.h idris_net.h
6+ idris_opts.h idris_stats.h mini-gmp.h idris_stdfgn.h idris_net.h \
7+ idris_utf8.h
78CFLAGS:=-fPIC $(CFLAGS)
89CFLAGS += $(GMP_INCLUDE_DIR) $(GMP) -DIDRIS_TARGET_OS="\"$(OS)\""
910CFLAGS += -DIDRIS_TARGET_TRIPLE="\"$(MACHINE)\""
rts/idris_bitstring.c−68
@@ -822,71 +822,3 @@ VAL idris_b64T32(VM *vm, VAL a) {
822822 return cl;
823823}
824824
825−// SSE vectors
826−VAL idris_IDXB8x16(VM* vm, VAL vec, VAL idx) {
827− __m128i sse = *vec->info.bits128p;
828− uint8_t data[16];
829− _mm_storeu_si128((__m128i*)&data, sse);
830− return MKB8(vm, data[idx->info.bits32]);
831−}
832−
833−VAL idris_IDXB16x8(VM* vm, VAL vec, VAL idx) {
834− __m128i sse = *vec->info.bits128p;
835− uint16_t data[8];
836− _mm_storeu_si128((__m128i*)&data, sse);
837− return MKB16(vm, data[idx->info.bits32]);
838−}
839−
840−VAL idris_IDXB32x4(VM* vm, VAL vec, VAL idx) {
841− __m128i sse = *vec->info.bits128p;
842− uint32_t data[4];
843− _mm_storeu_si128((__m128i*)&data, sse);
844− return MKB32(vm, data[idx->info.bits32]);
845−}
846−
847−VAL idris_IDXB64x2(VM* vm, VAL vec, VAL idx) {
848− __m128i sse = *vec->info.bits128p;
849− uint64_t data[2];
850− _mm_storeu_si128((__m128i*)&data, sse);
851− return MKB64(vm, data[idx->info.bits32]);
852−}
853−
854−VAL idris_b8x16CopyForGC(VM *vm, VAL vec) {
855− __m128i sse = *vec->info.bits128p;
856− VAL cl = allocate(sizeof(Closure) + 16 + sizeof(__m128i), 1);
857− SETTY(cl, BITS8X16);
858− cl->info.bits128p = (__m128i*)ALIGN((uintptr_t)cl + sizeof(Closure), 16);
859− assert ((uintptr_t)cl->info.bits128p % 16 == 0);
860− *cl->info.bits128p = sse;
861− return cl;
862−}
863−
864−VAL idris_b16x8CopyForGC(VM *vm, VAL vec) {
865− __m128i sse = *vec->info.bits128p;
866− VAL cl = allocate(sizeof(Closure) + 16 + sizeof(__m128i), 1);
867− SETTY(cl, BITS16X8);
868− cl->info.bits128p = (__m128i*)ALIGN((uintptr_t)cl + sizeof(Closure), 16);
869− assert ((uintptr_t)cl->info.bits128p % 16 == 0);
870− *cl->info.bits128p = sse;
871− return cl;
872−}
873−
874−VAL idris_b32x4CopyForGC(VM *vm, VAL vec) {
875− __m128i sse = *vec->info.bits128p;
876− VAL cl = allocate(sizeof(Closure) + 16 + sizeof(__m128i), 1);
877− SETTY(cl, BITS32X4);
878− cl->info.bits128p = (__m128i*)ALIGN((uintptr_t)cl + sizeof(Closure), 16);
879− assert ((uintptr_t)cl->info.bits128p % 16 == 0);
880− *cl->info.bits128p = sse;
881− return cl;
882−}
883−
884−VAL idris_b64x2CopyForGC(VM *vm, VAL vec) {
885− __m128i sse = *vec->info.bits128p;
886− VAL cl = allocate(sizeof(Closure) + 16 + sizeof(__m128i), 1);
887− SETTY(cl, BITS64X2);
888− cl->info.bits128p = (__m128i*)ALIGN((uintptr_t)cl + sizeof(Closure), 16);
889− assert ((uintptr_t)cl->info.bits128p % 16 == 0);
890− *cl->info.bits128p = sse;
891− return cl;
892−}
rts/idris_bitstring.h−10
@@ -126,14 +126,4 @@ VAL idris_b64T8(VM *vm, VAL a);
126126VAL idris_b64T16(VM *vm, VAL a);
127127VAL idris_b64T32(VM *vm, VAL a);
128128
129−VAL idris_IDXB8x16(VM* vm, VAL vec, VAL idx);
130−VAL idris_IDXB16x8(VM* vm, VAL vec, VAL idx);
131−VAL idris_IDXB32x4(VM* vm, VAL vec, VAL idx);
132−VAL idris_IDXB64x2(VM* vm, VAL vec, VAL idx);
133−
134−VAL idris_b8x16CopyForGC(VM *vm, VAL a);
135−VAL idris_b16x8CopyForGC(VM *vm, VAL a);
136−VAL idris_b32x4CopyForGC(VM *vm, VAL a);
137−VAL idris_b64x2CopyForGC(VM *vm, VAL a);
138−
139129#endif
rts/idris_gc.c−15
@@ -30,9 +30,6 @@ VAL copy(VM* vm, VAL x) {
3030 case STROFFSET:
3131 cl = MKSTROFFc(vm, x->info.str_offset);
3232 break;
33− case BUFFER:
34− cl = MKBUFFERc(vm, x->info.buf);
35− break;
3633 case BIGINT:
3734 cl = MKBIGMc(vm, x->info.ptr);
3835 break;
@@ -54,18 +51,6 @@ VAL copy(VM* vm, VAL x) {
5451 case BITS64:
5552 cl = idris_b64CopyForGC(vm, x);
5653 break;
57− case BITS8X16:
58− cl = idris_b8x16CopyForGC(vm, x);
59− break;
60− case BITS16X8:
61− cl = idris_b16x8CopyForGC(vm, x);
62− break;
63− case BITS32X4:
64− cl = idris_b32x4CopyForGC(vm, x);
65− break;
66− case BITS64X2:
67− cl = idris_b64x2CopyForGC(vm, x);
68− break;
6954 case FWD:
7055 return x->info.ptr;
7156 default:
rts/idris_rts.c+39−360
@@ -2,6 +2,7 @@
22
33#include "idris_rts.h"
44#include "idris_gc.h"
5+#include "idris_utf8.h"
56#include "idris_bitstring.h"
67
78#ifdef HAS_PTHREAD
@@ -326,107 +327,6 @@ VAL MKB64(VM* vm, uint64_t bits64) {
326327 return cl;
327328}
328329
329−VAL MKB8x16const(VM* vm,
330− uint8_t v0, uint8_t v1, uint8_t v2, uint8_t v3,
331− uint8_t v4, uint8_t v5, uint8_t v6, uint8_t v7,
332− uint8_t v8, uint8_t v9, uint8_t v10, uint8_t v11,
333− uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15) {
334− Closure* cl = allocate(sizeof(Closure) + sizeof(__m128i), 1);
335− SETTY(cl, BITS8X16);
336−
337− cl->info.bits128p = (__m128i*)ALIGN((uintptr_t)cl + sizeof(Closure), 16);
338− assert ((uintptr_t)cl->info.bits128p % 16 == 0);
339−
340− uint8_t data[16];
341− data[0]=v0; data[1]=v1; data[2]=v2; data[3]=v3;
342− data[4]=v4; data[5]=v5; data[6]=v6; data[7]=v7;
343− data[8]=v8; data[9]=v9; data[10]=v10; data[11]=v11;
344− data[12]=v12; data[13]=v13; data[14]=v14; data[15]=v15;
345−
346− *cl->info.bits128p = _mm_loadu_si128((__m128i*)&data);
347−
348− return cl;
349−}
350−
351−VAL MKB8x16(VM* vm,
352− VAL v0, VAL v1, VAL v2, VAL v3,
353− VAL v4, VAL v5, VAL v6, VAL v7,
354− VAL v8, VAL v9, VAL v10, VAL v11,
355− VAL v12, VAL v13, VAL v14, VAL v15) {
356− return MKB8x16const(vm,
357− v0->info.bits8, v1->info.bits8, v2->info.bits8, v3->info.bits8,
358− v4->info.bits8, v5->info.bits8, v6->info.bits8, v7->info.bits8,
359− v8->info.bits8, v9->info.bits8, v10->info.bits8, v11->info.bits8,
360− v12->info.bits8, v13->info.bits8, v14->info.bits8, v15->info.bits8);
361−}
362−
363−VAL MKB16x8const(VM* vm,
364− uint16_t v0, uint16_t v1, uint16_t v2, uint16_t v3,
365− uint16_t v4, uint16_t v5, uint16_t v6, uint16_t v7) {
366− Closure* cl = allocate(sizeof(Closure) + sizeof(__m128i), 1);
367− SETTY(cl, BITS16X8);
368−
369− cl->info.bits128p = (__m128i*)ALIGN((uintptr_t)cl + sizeof(Closure), 16);
370− assert ((uintptr_t)cl->info.bits128p % 16 == 0);
371−
372− uint16_t data[8];
373− data[0]=v0; data[1]=v1; data[2]=v2; data[3]=v3;
374− data[4]=v4; data[5]=v5; data[6]=v6; data[7]=v7;
375−
376− *cl->info.bits128p = _mm_loadu_si128((__m128i*)&data);
377− return cl;
378−
379−}
380−
381−VAL MKB16x8(VM* vm,
382− VAL v0, VAL v1, VAL v2, VAL v3,
383− VAL v4, VAL v5, VAL v6, VAL v7) {
384− return MKB16x8const(vm,
385− v0->info.bits16, v1->info.bits16, v2->info.bits16, v3->info.bits16,
386− v4->info.bits16, v5->info.bits16, v6->info.bits16, v7->info.bits16);
387−}
388−
389−VAL MKB32x4const(VM* vm,
390− uint32_t v0, uint32_t v1, uint32_t v2, uint32_t v3) {
391− Closure* cl = allocate(sizeof(Closure) + 16 + sizeof(__m128i), 1);
392− SETTY(cl, BITS64X2);
393−
394− cl->info.bits128p = (__m128i*)ALIGN((uintptr_t)cl + sizeof(Closure), 16);
395− assert ((uintptr_t)cl->info.bits128p % 16 == 0);
396−
397− uint32_t data[4];
398− data[0]=v0; data[1]=v1; data[2]=v2; data[3]=v3;
399−
400− *cl->info.bits128p = _mm_loadu_si128((__m128i*)&data);
401− return cl;
402−}
403−
404−VAL MKB32x4(VM* vm,
405− VAL v0, VAL v1, VAL v2, VAL v3) {
406− return MKB32x4const(vm,
407− v0->info.bits32, v1->info.bits32, v2->info.bits32, v3->info.bits32);
408−}
409−
410−VAL MKB64x2const(VM* vm, uint64_t v0, uint64_t v1) {
411− Closure* cl = allocate(sizeof(Closure) + 16 + sizeof(__m128i), 1);
412− SETTY(cl, BITS64X2);
413−
414− cl->info.bits128p = (__m128i*)ALIGN((uintptr_t)cl + sizeof(Closure), 16);
415− assert ((uintptr_t)cl->info.bits128p % 16 == 0);
416−
417− uint64_t data[2];
418− data[0]=v0; data[1]=v1;
419−
420− *cl->info.bits128p = _mm_loadu_si128((__m128i*)&data);
421− return cl;
422−}
423−
424−VAL MKB64x2(VM* vm, VAL v0, VAL v1) {
425− return MKB64x2const(vm,
426− v0->info.bits64,
427− v1->info.bits64);
428−}
429−
430330void PROJECT(VM* vm, VAL r, int loc, int arity) {
431331 int i;
432332 for(i = 0; i < arity; ++i) {
@@ -596,7 +496,7 @@ VAL idris_streq(VM* vm, VAL l, VAL r) {
596496}
597497
598498VAL idris_strlen(VM* vm, VAL l) {
599− return MKINT((i_int)(strlen(GETSTR(l))));
499+ return MKINT((i_int)(idris_utf8_strlen(GETSTR(l))));
600500}
601501
602502#define BUFSIZE 256
@@ -621,8 +521,16 @@ VAL idris_readStr(VM* vm, FILE* h) {
621521 {
622522 /* Make the buffer bigger and read more of the line */
623523 line_buf_size += BUFSIZE;
624− line_buf = (char *) realloc (line_buf, line_buf_size);
625−
524+ { /* limit the scope of new_line_buf to where it's needed for errors*/
525+ char *new_line_buf = realloc (line_buf, line_buf_size);
526+ if (new_line_buf == NULL)
527+ {
528+ fprintf(stderr, "Fatal Error: couldn't allocate a larger line buffer.");
529+ exit(EXIT_FAILURE);
530+ } else {
531+ line_buf = new_line_buf;
532+ }
533+ }
626534 /* points to last byte again */
627535 line_ptr = line_buf + line_buf_size - 1;
628536 /* so we can see if fgets put a 0 there */
@@ -639,7 +547,7 @@ VAL idris_readStr(VM* vm, FILE* h) {
639547}
640548
641549VAL idris_strHead(VM* vm, VAL str) {
642− return MKINT((i_int)(GETSTR(str)[0]));
550+ return idris_strIndex(vm, str, 0);
643551}
644552
645553VAL MKSTROFFc(VM* vm, StrOffset* off) {
@@ -671,27 +579,41 @@ VAL idris_strTail(VM* vm, VAL str) {
671579 }
672580
673581 cl->info.str_offset->str = root;
674− cl->info.str_offset->offset = offset+1;
582+ cl->info.str_offset->offset = offset+idris_utf8_charlen(GETSTR(str));
675583
676584 return cl;
677585 } else {
678− return MKSTR(vm, GETSTR(str)+1);
586+ char* nstr = GETSTR(str);
587+ return MKSTR(vm, nstr+idris_utf8_charlen(nstr));
679588 }
680589}
681590
682591VAL idris_strCons(VM* vm, VAL x, VAL xs) {
683592 char *xstr = GETSTR(xs);
684− Closure* cl = allocate(sizeof(Closure) +
685− strlen(xstr) + 2, 0);
686− SETTY(cl, STRING);
687− cl -> info.str = (char*)cl + sizeof(Closure);
688− cl -> info.str[0] = (char)(GETINT(x));
689− strcpy(cl -> info.str+1, xstr);
690− return cl;
593+ int xval = GETINT(x);
594+ if ((xval & 0x80) == 0) { // ASCII char
595+ Closure* cl = allocate(sizeof(Closure) +
596+ strlen(xstr) + 2, 0);
597+ SETTY(cl, STRING);
598+ cl -> info.str = (char*)cl + sizeof(Closure);
599+ cl -> info.str[0] = (char)(GETINT(x));
600+ strcpy(cl -> info.str+1, xstr);
601+ return cl;
602+ } else {
603+ char *init = idris_utf8_fromChar(xval);
604+ Closure* cl = allocate(sizeof(Closure) + strlen(init) + strlen(xstr) + 1, 0);
605+ SETTY(cl, STRING);
606+ cl -> info.str = (char*)cl + sizeof(Closure);
607+ strcpy(cl -> info.str, init);
608+ strcat(cl -> info.str, xstr);
609+ free(init);
610+ return cl;
611+ }
691612}
692613
693614VAL idris_strIndex(VM* vm, VAL str, VAL i) {
694− return MKINT((i_int)(GETSTR(str)[GETINT(i)]));
615+ int idx = idris_utf8_index(GETSTR(str), GETINT(i));
616+ return MKINT((i_int)idx);
695617}
696618
697619VAL idris_strRev(VM* vm, VAL str) {
@@ -699,14 +621,8 @@ VAL idris_strRev(VM* vm, VAL str) {
699621 Closure* cl = allocate(sizeof(Closure) +
700622 strlen(xstr) + 1, 0);
701623 SETTY(cl, STRING);
702− cl -> info.str = (char*)cl + sizeof(Closure);
703− int y = 0;
704− int x = strlen(xstr);
705−
706− cl-> info.str[x+1] = '\0';
707− while(x>0) {
708− cl -> info.str[y++] = xstr[--x];
709− }
624+ cl->info.str = (char*)cl + sizeof(Closure);
625+ idris_utf8_rev(xstr, cl->info.str);
710626 return cl;
711627}
712628
@@ -723,240 +639,6 @@ VAL idris_systemInfo(VM* vm, VAL index) {
723639 return MKSTR(vm, "");
724640}
725641
726−VAL MKBUFFERc(VM* vm, Buffer* buf) {
727− Closure* cl = allocate(sizeof(Closure) + sizeof *buf + buf->cap, 1);
728− SETTY(cl, BUFFER);
729− cl->info.buf = (Buffer*)((void*)cl + sizeof(Closure));
730− memmove(cl->info.buf, buf, sizeof *buf + buf->fill);
731− return cl;
732−}
733−
734−static VAL internal_allocate(VM *vm, size_t hint) {
735− size_t size = hint + sizeof(Closure) + sizeof(Buffer);
736−
737− // Round up to a power of 2
738− --size;
739− size_t i;
740− for (i = 0; i <= sizeof size; ++i)
741− size |= size >> (1 << i);
742− ++size;
743−
744− Closure* cl = allocate(size, 0);
745− SETTY(cl, BUFFER);
746− cl->info.buf = (Buffer*)((void*)cl + sizeof(Closure));
747− cl->info.buf->cap = size - (sizeof(Closure) + sizeof(Buffer));
748− return cl;
749−}
750−
751−// Following functions cast uint64_t to size_t, which may narrow!
752−VAL idris_buffer_allocate(VM* vm, VAL hint) {
753− Closure* cl = internal_allocate(vm, hint->info.bits64);
754− cl->info.buf->fill = 0;
755− return cl;
756−}
757−
758−static void internal_memset(void *dest, const void *src, size_t size, size_t num) {
759− while (num--) {
760− memmove(dest, src, size);
761− dest += size;
762− }
763−}
764−
765−static VAL internal_prepare_append(VM* vm, VAL buf, size_t bufLen, size_t appLen) {
766− size_t totalLen = bufLen + appLen;
767− Closure* cl;
768− if (bufLen != buf->info.buf->fill ||
769− totalLen > buf->info.buf->cap) {
770− // We're not at the fill or are over cap, so need a new buffer
771− cl = internal_allocate(vm, totalLen);
772− memmove(cl->info.buf->store,
773− buf->info.buf->store,
774− bufLen);
775− cl->info.buf->fill = totalLen;
776− } else {
777− // Hooray, can just bump the fill
778− cl = buf;
779− cl->info.buf->fill += appLen;
780− }
781− return cl;
782−}
783−
784−VAL idris_appendBuffer(VM* vm, VAL fst, VAL fstLen, VAL cnt, VAL sndLen, VAL sndOff, VAL snd) {
785− size_t firstLength = fstLen->info.bits64;
786− size_t secondLength = sndLen->info.bits64;
787− size_t count = cnt->info.bits64;
788− size_t offset = sndOff->info.bits64;
789− Closure* cl = internal_prepare_append(vm, fst, firstLength, count * secondLength);
790− internal_memset(cl->info.buf->store + firstLength, snd->info.buf->store + offset, secondLength, count);
791− return cl;
792−}
793−
794−// Special cased because we can use memset
795−VAL idris_appendB8Native(VM* vm, VAL buf, VAL len, VAL cnt, VAL val) {
796− size_t bufLen = len->info.bits64;
797− size_t count = cnt->info.bits64;
798− Closure* cl = internal_prepare_append(vm, buf, bufLen, count);
799− memset(cl->info.buf->store + bufLen, val->info.bits8, count);
800− return cl;
801−}
802−
803−static VAL internal_append_bits(VM* vm, VAL buf, VAL bufLen, VAL cnt, const void* val, size_t val_len) {
804− size_t len = bufLen->info.bits64;
805− size_t count = cnt->info.bits64;
806− Closure* cl = internal_prepare_append(vm, buf, len, count * val_len);
807− internal_memset(cl->info.buf->store + len, val, val_len, count);
808− return cl;
809−}
810−
811−VAL idris_appendB16Native(VM* vm, VAL buf, VAL len, VAL cnt, VAL val) {
812− return internal_append_bits(vm, buf, len, cnt, &val->info.bits16, sizeof val->info.bits16);
813−}
814−
815−VAL idris_appendB16LE(VM* vm, VAL buf, VAL len, VAL cnt, VAL val) {
816− // On gcc 4.8 -O3 compiling for x86_64, using leVal like this is
817− // optimized away. Presumably the same holds for other sizes and
818− // conversly on BE systems
819− unsigned char leVal[sizeof val] = { val->info.bits16
820− , (val->info.bits16 >> 8)
821− };
822− return internal_append_bits(vm, buf, len, cnt, leVal, sizeof leVal);
823−}
824−
825−VAL idris_appendB16BE(VM* vm, VAL buf, VAL len, VAL cnt, VAL val) {
826− unsigned char beVal[sizeof val] = { (val->info.bits16 >> 8)
827− , val->info.bits16
828− };
829− return internal_append_bits(vm, buf, len, cnt, beVal, sizeof beVal);
830−}
831−
832−VAL idris_appendB32Native(VM* vm, VAL buf, VAL len, VAL cnt, VAL val) {
833− return internal_append_bits(vm, buf, len, cnt, &val->info.bits32, sizeof val->info.bits32);
834−}
835−
836−VAL idris_appendB32LE(VM* vm, VAL buf, VAL len, VAL cnt, VAL val) {
837− unsigned char leVal[sizeof val] = { val->info.bits32
838− , (val->info.bits32 >> 8)
839− , (val->info.bits32 >> 16)
840− , (val->info.bits32 >> 24)
841− };
842− return internal_append_bits(vm, buf, len, cnt, leVal, sizeof leVal);
843−}
844−
845−VAL idris_appendB32BE(VM* vm, VAL buf, VAL len, VAL cnt, VAL val) {
846− unsigned char beVal[sizeof val] = { (val->info.bits32 >> 24)
847− , (val->info.bits32 >> 16)
848− , (val->info.bits32 >> 8)
849− , val->info.bits32
850− };
851− return internal_append_bits(vm, buf, len, cnt, beVal, sizeof beVal);
852−}
853−
854−VAL idris_appendB64Native(VM* vm, VAL buf, VAL len, VAL cnt, VAL val) {
855− return internal_append_bits(vm, buf, len, cnt, &val->info.bits64, sizeof val->info.bits64);
856−}
857−
858−VAL idris_appendB64LE(VM* vm, VAL buf, VAL len, VAL cnt, VAL val) {
859− unsigned char leVal[sizeof val] = { val->info.bits64
860− , (val->info.bits64 >> 8)
861− , (val->info.bits64 >> 16)
862− , (val->info.bits64 >> 24)
863− , (val->info.bits64 >> 32)
864− , (val->info.bits64 >> 40)
865− , (val->info.bits64 >> 48)
866− , (val->info.bits64 >> 56)
867− };
868− return internal_append_bits(vm, buf, len, cnt, leVal, sizeof leVal);
869−}
870−
871−VAL idris_appendB64BE(VM* vm, VAL buf, VAL len, VAL cnt, VAL val) {
872− unsigned char beVal[sizeof val] = { (val->info.bits64 >> 56)
873− , (val->info.bits64 >> 48)
874− , (val->info.bits64 >> 40)
875− , (val->info.bits64 >> 32)
876− , (val->info.bits64 >> 24)
877− , (val->info.bits64 >> 16)
878− , (val->info.bits64 >> 8)
879− , val->info.bits64
880− };
881− return internal_append_bits(vm, buf, len, cnt, beVal, sizeof beVal);
882−}
883−
884−VAL idris_peekB8Native(VM* vm, VAL buf, VAL off) {
885− size_t offset = off->info.bits64;
886− uint8_t *val = buf->info.buf->store + offset;
887− return MKB8(vm, *val);
888−}
889−
890−VAL idris_peekB16Native(VM* vm, VAL buf, VAL off) {
891− size_t offset = off->info.bits64;
892− uint16_t *val = (uint16_t *) (buf->info.buf->store + offset);
893− return MKB16(vm, *val);
894−}
895−
896−VAL idris_peekB16LE(VM* vm, VAL buf, VAL off) {
897− size_t offset = off->info.bits64;
898− return MKB16(vm, ((uint16_t) buf->info.buf->store[offset]) +
899− (((uint16_t) buf->info.buf->store[offset + 1]) << 8));
900−}
901−
902−VAL idris_peekB16BE(VM* vm, VAL buf, VAL off) {
903− size_t offset = off->info.bits64;
904− return MKB16(vm, ((uint16_t) buf->info.buf->store[offset + 1]) +
905− (((uint16_t) buf->info.buf->store[offset]) << 8));
906−}
907−
908−VAL idris_peekB32Native(VM* vm, VAL buf, VAL off) {
909− size_t offset = off->info.bits64;
910− uint32_t *val = (uint32_t *) (buf->info.buf->store + offset);
911− return MKB32(vm, *val);
912−}
913−
914−VAL idris_peekB32LE(VM* vm, VAL buf, VAL off) {
915− size_t offset = off->info.bits64;
916− return MKB32(vm, ((uint32_t) buf->info.buf->store[offset]) +
917− (((uint32_t) buf->info.buf->store[offset + 1]) << 8) +
918− (((uint32_t) buf->info.buf->store[offset + 2]) << 16) +
919− (((uint32_t) buf->info.buf->store[offset + 3]) << 24));
920−}
921−
922−VAL idris_peekB32BE(VM* vm, VAL buf, VAL off) {
923− size_t offset = off->info.bits64;
924− return MKB32(vm, ((uint32_t) buf->info.buf->store[offset + 3]) +
925− (((uint32_t) buf->info.buf->store[offset + 2]) << 8) +
926− (((uint32_t) buf->info.buf->store[offset + 1]) << 16) +
927− (((uint32_t) buf->info.buf->store[offset]) << 24));
928−}
929−
930−VAL idris_peekB64Native(VM* vm, VAL buf, VAL off) {
931− size_t offset = off->info.bits64;
932− uint64_t *val = (uint64_t *) (buf->info.buf->store + offset);
933− return MKB64(vm, *val);
934−}
935−
936−VAL idris_peekB64LE(VM* vm, VAL buf, VAL off) {
937− size_t offset = off->info.bits64;
938− return MKB64(vm, ((uint64_t) buf->info.buf->store[offset]) +
939− (((uint64_t) buf->info.buf->store[offset + 1]) << 8) +
940− (((uint64_t) buf->info.buf->store[offset + 2]) << 16) +
941− (((uint64_t) buf->info.buf->store[offset + 3]) << 24) +
942− (((uint64_t) buf->info.buf->store[offset + 4]) << 32) +
943− (((uint64_t) buf->info.buf->store[offset + 5]) << 40) +
944− (((uint64_t) buf->info.buf->store[offset + 6]) << 48) +
945− (((uint64_t) buf->info.buf->store[offset + 7]) << 56));
946−}
947−
948−VAL idris_peekB64BE(VM* vm, VAL buf, VAL off) {
949− size_t offset = off->info.bits64;
950− return MKB64(vm, ((uint64_t) buf->info.buf->store[offset + 7]) +
951− (((uint64_t) buf->info.buf->store[offset + 6]) << 8) +
952− (((uint64_t) buf->info.buf->store[offset + 5]) << 16) +
953− (((uint64_t) buf->info.buf->store[offset + 4]) << 24) +
954− (((uint64_t) buf->info.buf->store[offset + 3]) << 32) +
955− (((uint64_t) buf->info.buf->store[offset + 2]) << 40) +
956− (((uint64_t) buf->info.buf->store[offset + 1]) << 48) +
957− (((uint64_t) buf->info.buf->store[offset]) << 56));
958−}
959−
960642typedef struct {
961643 VM* vm; // thread's VM
962644 VM* callvm; // calling thread's VM
@@ -1041,9 +723,6 @@ VAL doCopyTo(VM* vm, VAL x) {
1041723 case STRING:
1042724 cl = MKSTRc(vm, x->info.str);
1043725 break;
1044− case BUFFER:
1045− cl = MKBUFFERc(vm, x->info.buf);
1046− break;
1047726 case BIGINT:
1048727 cl = MKBIGMc(vm, x->info.ptr);
1049728 break;
rts/idris_rts.h+3−30
@@ -26,8 +26,7 @@
2626typedef enum {
2727 CON, INT, BIGINT, FLOAT, STRING, STROFFSET,
2828 BITS8, BITS16, BITS32, BITS64, UNIT, PTR, FWD,
29− MANAGEDPTR, BUFFER, BITS8X16, BITS16X8, BITS32X4,
30− BITS64X2
29+ MANAGEDPTR
3130} ClosureType;
3231
3332typedef struct Closure *VAL;
@@ -208,37 +207,12 @@ VAL MKB16(VM* vm, uint16_t b);
208207VAL MKB32(VM* vm, uint32_t b);
209208VAL MKB64(VM* vm, uint64_t b);
210209
211−// SSE Vectors
212−VAL MKB8x16(VM* vm,
213− VAL v0, VAL v1, VAL v2, VAL v3,
214− VAL v4, VAL v5, VAL v6, VAL v7,
215− VAL v8, VAL v9, VAL v10, VAL v11,
216− VAL v12, VAL v13, VAL v14, VAL v15);
217−VAL MKB8x16const(VM* vm,
218− uint8_t v0, uint8_t v1, uint8_t v2, uint8_t v3,
219− uint8_t v4, uint8_t v5, uint8_t v6, uint8_t v7,
220− uint8_t v8, uint8_t v9, uint8_t v10, uint8_t v11,
221− uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15);
222−VAL MKB16x8(VM* vm,
223− VAL v0, VAL v1, VAL v2, VAL v3,
224− VAL v4, VAL v5, VAL v6, VAL v7);
225−VAL MKB16x8const(VM* vm,
226− uint16_t v0, uint16_t v1, uint16_t v2, uint16_t v3,
227− uint16_t v4, uint16_t v5, uint16_t v6, uint16_t v7);
228−VAL MKB32x4(VM* vm,
229− VAL v0, VAL v1, VAL v2, VAL v3);
230−VAL MKB32x4const(VM* vm,
231− uint32_t v0, uint32_t v1, uint32_t v2, uint32_t v3);
232−VAL MKB64x2(VM* vm, VAL v0, VAL v1);
233−VAL MKB64x2const(VM* vm, uint64_t v0, uint64_t v1);
234−
235210// following versions don't take a lock when allocating
236211VAL MKFLOATc(VM* vm, double val);
237212VAL MKSTROFFc(VM* vm, StrOffset* off);
238213VAL MKSTRc(VM* vm, char* str);
239214VAL MKPTRc(VM* vm, void* ptr);
240215VAL MKMPTRc(VM* vm, void* ptr, size_t size);
241−VAL MKBUFFERc(VM* vm, Buffer* buf);
242216
243217char* GETSTROFF(VAL stroff);
244218
@@ -335,13 +309,12 @@ VAL idris_readStr(VM* vm, FILE* h);
335309
336310VAL idris_strHead(VM* vm, VAL str);
337311VAL idris_strTail(VM* vm, VAL str);
312+// This is not expected to be efficient! Mostly we wouldn't expect to call
313+// it at all at run time.
338314VAL idris_strCons(VM* vm, VAL x, VAL xs);
339315VAL idris_strIndex(VM* vm, VAL str, VAL i);
340316VAL idris_strRev(VM* vm, VAL str);
341317
342−// Buffer primitives
343−VAL idris_buffer_allocate(VM* vm, VAL hint);
344−VAL idris_appendBuffer(VM* vm, VAL fst, VAL fstLen, VAL cnt, VAL sndLen, VAL sndOff, VAL snd);
345318VAL idris_appendB8Native(VM* vm, VAL buf, VAL len, VAL cnt, VAL val);
346319VAL idris_appendB16Native(VM* vm, VAL buf, VAL len, VAL cnt, VAL val);
347320VAL idris_appendB16LE(VM* vm, VAL buf, VAL len, VAL cnt, VAL val);
rts/idris_utf8.cnew file+144
@@ -0,0 +1,144 @@
1+#include "idris_utf8.h"
2+#include <stdio.h>
3+#include <string.h>
4+#include <stdlib.h>
5+
6+int idris_utf8_strlen(char *s) {
7+ int i = 0, j = 0;
8+ while (s[i]) {
9+ if ((s[i] & 0xc0) != 0x80) j++;
10+ i++;
11+ }
12+ return j;
13+}
14+
15+int idris_utf8_charlen(char* s) {
16+ int init = (int)s[0];
17+ if ((init & 0x80) == 0) {
18+ return 1; // Top bit unset, so 1 byte
19+ }
20+ if ((init > 244 && init < 256) ||
21+ (init == 192) ||
22+ (init == 193)) {
23+ return 1; // Invalid characters
24+ }
25+ int i = 1;
26+ while ((s[i] & 0xc0) == 0x80) {
27+ i++; // Move on until top 2 bits are not 10
28+ }
29+ return i;
30+}
31+
32+unsigned idris_utf8_index(char* s, int idx) {
33+ int i = 0, j = 0;
34+ while (j < idx) {
35+ if ((s[i] & 0xc0) != 0x80) j++;
36+ i++;
37+ }
38+ // Find the start of the next character
39+ while ((s[i] & 0xc0) == 0x80) { i++; }
40+
41+ unsigned bytes = 0;
42+ unsigned top = 0;
43+
44+ int init = (int)s[1];
45+
46+ // s[i] is now the start of the character we want
47+ if ((s[i] & 0x80) == 0) {
48+ bytes = 1;
49+ top = (int)(s[i]);
50+ } else if ((init > 244 && init < 256) ||
51+ (init == 192) ||
52+ (init == 193)) {
53+ bytes = 1;
54+ top = (int)(s[i]); // Invalid characters
55+ } else if ((s[i] & 0xe0) == 0xc0) {
56+ bytes = 2;
57+ top = (int)(s[i] & 0x1f); // 5 bits
58+ } else if ((s[i] & 0xf0) == 0xe0) {
59+ bytes = 3;
60+ top = (int)(s[i] & 0x0f); // 4 bits
61+ } else if ((s[i] & 0xf8) == 0xf0) {
62+ bytes = 4;
63+ top = (int)(s[i] & 0x07); // 3 bits
64+ } else if ((s[i] & 0xfc) == 0xf8) {
65+ bytes = 5;
66+ top = (int)(s[i] & 0x03); // 2 bits
67+ } else if ((s[i] & 0xfe) == 0xfc) {
68+ bytes = 6;
69+ top = (int)(s[i] & 0x01); // 1 bits
70+ }
71+
72+ while (bytes > 1) {
73+ top = top << 6;
74+ top += s[++i] & 0x3f; // 6 bits
75+ --bytes;
76+ }
77+
78+ return top;
79+}
80+
81+char* idris_utf8_fromChar(int x) {
82+ char* str;
83+ int bytes = 0, top = 0;
84+
85+ if ((x & 0x80) == 0) {
86+ str = malloc(2);
87+ str[0] = (char)x;
88+ str[1] = '\0';
89+ return str;
90+ }
91+
92+ if (x >= 0x80 && x <= 0x7ff) {
93+ bytes = 2;
94+ top = 0xc0;
95+ } else if (x >= 0x800 && x <= 0xffff) {
96+ bytes = 3;
97+ top = 0xe0;
98+ } else if (x >= 0x10000 && x <= 0x10ffff) {
99+ bytes = 4;
100+ top = 0xf0;
101+ }
102+
103+ str = malloc(bytes + 1);
104+ str[bytes] = '\0';
105+ while(bytes > 0) {
106+ int xbits = x & 0x3f; // Next 6 bits
107+ bytes--;
108+ if (bytes > 0) {
109+ str[bytes] = (char)xbits + 0x80;
110+ } else {
111+ str[0] = (char)xbits + top;
112+ }
113+ x = x >> 6;
114+ }
115+
116+ return str;
117+}
118+
119+void reverse_range(char *start, char *end)
120+{
121+ while(start < end)
122+ {
123+ char c = *start;
124+ *start++ = *end;
125+ *end-- = c;
126+ }
127+}
128+
129+char* reverse_char(char *start)
130+{
131+ char *end = start;
132+ while((end[1] & 0xc0) == 0x80) { end++; }
133+ reverse_range(start, end);
134+ return(end + 1);
135+}
136+
137+char* idris_utf8_rev(char* s, char* result) {
138+ strcpy(result, s);
139+ char* end = result;
140+ while(*end) { end = reverse_char(end); }
141+ reverse_range(result, end-1);
142+ return result;
143+}
144+
rts/idris_utf8.hnew file+22
@@ -0,0 +1,22 @@
1+#ifndef _IDRIS_UTF8
2+#define _IDRIS_UTF8
3+
4+/* Various functions for dealing with UTF8 encoding. These are probably
5+ not very efficient (and I'm (EB) making no guarantees about their
6+ correctness.) Nevertheless, they mean that we can treat Strings as
7+ UFT8. Patches welcome :). */
8+
9+// Get length of a UTF8 encoded string in characters
10+int idris_utf8_strlen(char *s);
11+// Get number of bytes the first character takes in a string
12+int idris_utf8_charlen(char* s);
13+// Return int representation of string at an index.
14+// Assumes in bounds.
15+unsigned idris_utf8_index(char* s, int j);
16+// Convert a char as an integer to a char* as a byte sequence
17+// Null terminated; caller responsible for freeing
18+char* idris_utf8_fromChar(int x);
19+// Reverse a UTF8 encoded string, putting the result in 'result'
20+char* idris_utf8_rev(char* s, char* result);
21+
22+#endif
samples/ConsoleIO.idrnew file+15
@@ -0,0 +1,15 @@
1+module Main
2+
3+import Effects
4+import Effect.StdIO
5+import Effect.State
6+
7+hello : { [STATE Int, STDIO] } Eff ()
8+hello = do putStr "Name? "
9+ putStrLn ("Hello " ++ trim !getStr ++ "!")
10+ update (+1)
11+ putStrLn ("I've said hello to: " ++ show !get ++ " people")
12+ hello
13+
14+main : IO ()
15+main = run hello
samples/Exception.idrnew file+21
@@ -0,0 +1,21 @@
1+module Main
2+
3+import Effects
4+import Effect.Exception
5+import Effect.StdIO
6+import Control.IOExcept
7+
8+data MyErr = NotANumber | OutOfRange
9+
10+instance Show MyErr where
11+ show NotANumber = "Not a number"
12+ show OutOfRange = "Out of range"
13+
14+parseNumber : Int -> String -> { [EXCEPTION MyErr] } Eff Int
15+parseNumber num str
16+ = if all isDigit (unpack str)
17+ then let x = cast str in
18+ if (x >=0 && x <= num)
19+ then pure x
20+ else raise OutOfRange
21+ else raise NotANumber
samples/Makefile+2−2
@@ -2,7 +2,7 @@ check:
22 rm -f *.ibc
33 for x in *.idr ; do \
44 echo "Checking $$x"; \
5− idris --check $$x; \
5+ idris -p effects --check $$x; \
66 done
7−
7+
88.PHONY: check
samples/Random.idrnew file+37
@@ -0,0 +1,37 @@
1+module Main
2+
3+import Effects
4+import Effect.Random
5+import Effect.Exception
6+import Effect.StdIO
7+
8+data MyErr = NotANumber | OutOfRange
9+
10+parseNumber : Int -> String -> { [EXCEPTION MyErr] } Eff Int
11+parseNumber num str
12+ = if all isDigit (unpack str)
13+ then let x = cast str in
14+ if (x >=0 && x <= num)
15+ then pure x
16+ else raise OutOfRange
17+ else raise NotANumber
18+
19+guess : Int -> { [STDIO] } Eff ()
20+guess target
21+ = do putStr "Guess: "
22+ case run {m=Maybe} (parseNumber 100 (trim !getStr)) of
23+ Nothing => do putStrLn "Invalid input"
24+ guess target
25+ Just v => case compare v target of
26+ LT => do putStrLn "Too low"
27+ guess target
28+ EQ => putStrLn "You win!"
29+ GT => do putStrLn "Too high"
30+ guess target
31+
32+game : { [RND, STDIO] } Eff ()
33+game = do srand 123456789
34+ guess (fromInteger !(rndInt 0 100))
35+
36+main : IO ()
37+main = run game
samples/ReadInt.idrnew file+22
@@ -0,0 +1,22 @@
1+module ReadInt
2+
3+import Effects
4+import Effect.State
5+import Effect.StdIO
6+
7+readInt : { [STATE (Vect n Int), STDIO] ==>
8+ {ok} if ok then [STATE (Vect (S n) Int), STDIO]
9+ else [STATE (Vect n Int), STDIO] } Eff Bool
10+readInt = do let x = trim !getStr
11+ case all isDigit (unpack x) of
12+ False => pure False
13+ True => do updateM (\xs => cast x ::xs)
14+ pure True
15+
16+readN : (n : Nat) ->
17+ { [STATE (Vect m Int), STDIO] ==>
18+ [STATE (Vect (n + m) Int), STDIO] } Eff ()
19+readN Z = pure ()
20+readN {m} (S k) = case !readInt of
21+ True => rewrite plusSuccRightSucc k m in readN k
22+ False => readN (S k)
samples/Select.idrnew file+17
@@ -0,0 +1,17 @@
1+module Main
2+
3+import Effects
4+import Effect.Select
5+import Effect.Exception
6+
7+triple : Int -> { [SELECT, EXCEPTION String] } Eff (Int, Int, Int)
8+triple max = do z <- select [1..max]
9+ y <- select [1..z]
10+ x <- select [1..y]
11+ if (x * x + y * y == z * z)
12+ then pure (x, y, z)
13+ else raise "No triple"
14+
15+main : IO ()
16+main = do print $ the (Maybe _) $ run (triple 100)
17+ print $ the (List _) $ run (triple 100)
samples/TreeTag-noeff.idrnew file+21
@@ -0,0 +1,21 @@
1+
2+data BTree a = Leaf
3+ | Node (BTree a) a (BTree a)
4+
5+testTree : BTree String
6+testTree = Node (Node Leaf "Jim" Leaf)
7+ "Fred"
8+ (Node (Node Leaf "Alice" Leaf)
9+ "Sheila"
10+ (Node Leaf "Bob" Leaf))
11+
12+treeTagAux : (i : Int) -> BTree a -> (Int, BTree (Int, a))
13+treeTagAux i Leaf = (i, Leaf)
14+treeTagAux i (Node l x r)
15+ = let (i', l') = treeTagAux i l in
16+ let x' = (i', x) in
17+ let (i'', r') = treeTagAux (i' + 1) r in
18+ (i'', Node l' x' r')
19+
20+treeTag : (i : Int) -> BTree a -> BTree (Int, a)
21+treeTag i x = snd (treeTagAux i x)
samples/TreeTag.idrnew file+40
@@ -0,0 +1,40 @@
1+module Main
2+
3+import Effects
4+import Effect.State
5+
6+data BTree a = Leaf
7+ | Node (BTree a) a (BTree a)
8+
9+instance Show a => Show (BTree a) where
10+ show Leaf = "[]"
11+ show (Node l x r) = "[" ++ show l ++ " "
12+ ++ show x ++ " "
13+ ++ show r ++ "]"
14+
15+testTree : BTree String
16+testTree = Node (Node Leaf "Jim" Leaf)
17+ "Fred"
18+ (Node (Node Leaf "Alice" Leaf)
19+ "Sheila"
20+ (Node Leaf "Bob" Leaf))
21+
22+treeTagAux : BTree a -> { [STATE Int] } Eff (BTree (Int, a))
23+treeTagAux Leaf = return Leaf
24+treeTagAux (Node l x r)
25+ = do l' <- treeTagAux l
26+ i <- get
27+ put (i + 1)
28+ r' <- treeTagAux r
29+ return (Node l' (i, x) r')
30+
31+treeTag : (i : Int) -> BTree a -> BTree (Int, a)
32+treeTag i x = runPure (do put i
33+ treeTagAux x)
34+
35+treeTagIO : (i : Int) -> BTree a -> IO (BTree (Int, a))
36+treeTagIO i x = run (do put i
37+ treeTagAux x)
38+
39+main : IO ()
40+main = print (treeTag 1 testTree)
samples/TreeTagCount.idrnew file+29
@@ -0,0 +1,29 @@
1+import Effects
2+import Effect.State
3+import Effect.StdIO
4+
5+data BTree a = Leaf
6+ | Node (BTree a) a (BTree a)
7+
8+testTree : BTree String
9+testTree = Node (Node Leaf "Jim" Leaf)
10+ "Fred"
11+ (Node (Node Leaf "Alice" Leaf)
12+ "Sheila"
13+ (Node Leaf "Bob" Leaf))
14+
15+treeTagAux : BTree a -> { ['Tag ::: STATE Int,
16+ 'Leaves ::: STATE Int] } Eff (BTree (Int, a))
17+treeTagAux Leaf = do 'Leaves :- update (+1)
18+ pure Leaf
19+treeTagAux (Node l x r)
20+ = do l' <- treeTagAux l
21+ i <- 'Tag :- get
22+ 'Tag :- put (i + 1)
23+ r' <- treeTagAux r
24+ pure (Node l' (i, x) r')
25+
26+treeTag : (i : Int) -> BTree a -> (BTree (Int, a), Int)
27+treeTag i x = runPureInit ['Tag := i, 'Leaves := 0]
28+ (do x' <- treeTagAux x
29+ pure (x', !('Leaves :- get)))
samples/binary.idr+1−1
@@ -41,7 +41,7 @@ adc (numx # bx) (numy # by) carry
4141main : IO ()
4242main = do let n1 = zero # b1 # b0 # b1 # b0
4343 let n2 = zero # b1 # b1 # b1 # b0
44− printLn (adc n1 n2 b0)
44+ print (adc n1 n2 b0)
4545
4646
4747
samples/hworld.idrnew file+10
@@ -0,0 +1,10 @@
1+module Main
2+
3+import Effects
4+import Effect.StdIO
5+
6+hello : { [STDIO] } Eff ()
7+hello = putStrLn "Hello world!"
8+
9+main : IO ()
10+main = run hello
samples/vadd.idrnew file+41
@@ -0,0 +1,41 @@
1+module Main
2+
3+import Effects
4+import Effect.Exception
5+import Effect.StdIO
6+
7+parseNumber : String -> { [EXCEPTION String] } Eff Int
8+parseNumber str
9+ = if all (\x => isDigit x || x == '-') (unpack str)
10+ then pure (cast str)
11+ else raise "Not a number"
12+
13+vadd : Vect n Int -> Vect n Int -> Vect n Int
14+vadd [] [] = []
15+vadd (x :: xs) (y :: ys) = x + y :: vadd xs ys
16+
17+vadd_check : Vect n Int -> Vect m Int ->
18+ { [EXCEPTION String] } Eff (Vect m Int)
19+vadd_check {n} {m} xs ys with (decEq n m)
20+ vadd_check {n} {m=n} xs ys | (Yes Refl) = pure (vadd xs ys)
21+ vadd_check {n} {m} xs ys | (No _) = raise "Length mismatch"
22+
23+read_vec : { [STDIO] } Eff (p ** Vect p Int)
24+read_vec = do putStr "Number (-1 when done): "
25+ case run {m=Maybe} (parseNumber (trim !getStr)) of
26+ Nothing => do putStrLn "Input error"
27+ read_vec
28+ Just v => if (v /= -1)
29+ then do (_ ** xs) <- read_vec
30+ pure (_ ** v :: xs)
31+ else pure (_ ** [])
32+
33+do_vadd : { [STDIO, EXCEPTION String] } Eff ()
34+do_vadd = do putStrLn "Vector 1"
35+ (_ ** xs) <- read_vec
36+ putStrLn "Vector 2"
37+ (_ ** ys) <- read_vec
38+ putStrLn (show !(vadd_check xs ys))
39+
40+main : IO ()
41+main = run do_vadd
src/IRTS/CodegenC.hs+56−50
@@ -12,8 +12,8 @@ import Util.System
1212
1313import Numeric
1414import Data.Char
15+import Data.Bits
1516import Data.List (intercalate)
16−import qualified Data.Vector.Unboxed as V
1717import System.Process
1818import System.Exit
1919import System.IO
@@ -145,8 +145,26 @@ showCStr s = '"' : foldr ((++) . showChar) "\"" s
145145 | ord c < 0x10 = "\"\"\\x0" ++ showHex (ord c) "\"\""
146146 | ord c < 0x20 = "\"\"\\x" ++ showHex (ord c) "\"\""
147147 | ord c < 0x7f = [c] -- 0x7f = \DEL
148− | ord c < 0x100 = "\"\"\\x" ++ showHex (ord c) "\"\""
149− | otherwise = error $ "non-8-bit character in string literal: " ++ show c
148+ | otherwise = showHexes (utf8bytes (ord c))
149+
150+ utf8bytes :: Int -> [Int]
151+ utf8bytes x = let (h : bytes) = split [] x in
152+ headHex h (length bytes) : map toHex bytes
153+ where
154+ split acc 0 = acc
155+ split acc x = let xbits = x .&. 0x3f
156+ xrest = shiftR x 6 in
157+ split (xbits : acc) xrest
158+
159+ headHex h 1 = h + 0xc0
160+ headHex h 2 = h + 0xe0
161+ headHex h 3 = h + 0xf0
162+ headHex h n = error "Can't happen: Invalid UTF8 character"
163+
164+ toHex i = i + 0x80
165+
166+ showHexes = foldr ((++) . showUTF8) ""
167+ showUTF8 c = "\"\"\\x" ++ showHex c "\"\""
150168
151169bcc :: Int -> BC -> String
152170bcc i (ASSIGN l r) = indent i ++ creg l ++ " = " ++ creg r ++ ";\n"
@@ -163,10 +181,6 @@ bcc i (ASSIGNCONST l c)
163181 mkConst (B16 x) = "idris_b16const(vm, " ++ show x ++ "U)"
164182 mkConst (B32 x) = "idris_b32const(vm, " ++ show x ++ "UL)"
165183 mkConst (B64 x) = "idris_b64const(vm, " ++ show x ++ "ULL)"
166− mkConst (B8V x) = let x' = V.toList x in "MKB8x16const(vm, " ++ intercalate ", " (map (\elem -> show elem ++ "U") x') ++ ")"
167− mkConst (B16V x) = let x' = V.toList x in "MKB16x8const(vm, " ++ intercalate ", " (map (\elem -> show elem ++ "U") x') ++ ")"
168− mkConst (B32V x) = let x' = V.toList x in "MKB32x4const(vm, " ++ intercalate ", " (map (\elem -> show elem ++ "UL") x') ++ ")"
169− mkConst (B64V x) = let x' = V.toList x in "MKB64x2const(vm, " ++ intercalate ", " (map (\elem -> show elem ++ "ULL") x') ++ ")"
170184 -- if it's a type constant, we won't use it, but equally it shouldn't
171185 -- report an error. These might creep into generated for various reasons
172186 -- (especially if erasure is disabled).
@@ -305,10 +319,6 @@ toAType (FCon i)
305319 | i == sUN "C_IntBits16" = ATInt (ITFixed IT16)
306320 | i == sUN "C_IntBits32" = ATInt (ITFixed IT32)
307321 | i == sUN "C_IntBits64" = ATInt (ITFixed IT64)
308− | i == sUN "C_IntB8x16" = ATInt (ITVec IT8 16)
309− | i == sUN "C_IntB16x8" = ATInt (ITVec IT16 8)
310− | i == sUN "C_IntB32x4" = ATInt (ITVec IT32 4)
311− | i == sUN "C_IntB64x2" = ATInt (ITVec IT64 2)
312322toAType t = error (show t ++ " not defined in toAType")
313323
314324toFType (FCon c)
@@ -424,11 +434,6 @@ doOp v (LSLe (ATInt ITBig)) [l, r] = v ++ "idris_bigLe(vm, " ++ creg l ++ ", " +
424434doOp v (LSGt (ATInt ITBig)) [l, r] = v ++ "idris_bigGt(vm, " ++ creg l ++ ", " ++ creg r ++ ")"
425435doOp v (LSGe (ATInt ITBig)) [l, r] = v ++ "idris_bigGe(vm, " ++ creg l ++ ", " ++ creg r ++ ")"
426436
427−doOp v LStrConcat [l,r] = v ++ "idris_concat(vm, " ++ creg l ++ ", " ++ creg r ++ ")"
428−doOp v LStrLt [l,r] = v ++ "idris_strlt(vm, " ++ creg l ++ ", " ++ creg r ++ ")"
429−doOp v LStrEq [l,r] = v ++ "idris_streq(vm, " ++ creg l ++ ", " ++ creg r ++ ")"
430−doOp v LStrLen [x] = v ++ "idris_strlen(vm, " ++ creg x ++ ")"
431−
432437doOp v (LIntFloat ITNative) [x] = v ++ "idris_castIntFloat(" ++ creg x ++ ")"
433438doOp v (LFloatInt ITNative) [x] = v ++ "idris_castFloatInt(" ++ creg x ++ ")"
434439doOp v (LSExt ITNative ITBig) [x] = v ++ "idris_castIntBig(vm, " ++ creg x ++ ")"
@@ -441,16 +446,6 @@ doOp v (LIntStr (ITFixed _)) [x] = v ++ "idris_castBitsStr(vm, " ++ creg x ++ ")
441446doOp v LFloatStr [x] = v ++ "idris_castFloatStr(vm, " ++ creg x ++ ")"
442447doOp v LStrFloat [x] = v ++ "idris_castStrFloat(vm, " ++ creg x ++ ")"
443448
444−doOp v LReadStr [_] = v ++ "idris_readStr(vm, stdin)"
445−doOp v LWriteStr [_,s] = v ++ "MKINT((i_int)(idris_writeStr(stdout"
446− ++ ",GETSTR("
447− ++ creg s ++ "))))"
448−
449−doOp v LReadFile [_,x] = v ++ "idris_readStr(vm, GETPTR(" ++ creg x ++ "))"
450−doOp v LWriteFile [_,x,s] = v ++ "MKINT((i_int)(idris_writeStr(GETPTR(" ++ creg x
451− ++ "),GETSTR("
452− ++ creg s ++ "))))"
453−
454449doOp v (LSLt (ATInt (ITFixed ty))) [x, y] = bitOp v "SLt" ty [x, y]
455450doOp v (LSLe (ATInt (ITFixed ty))) [x, y] = bitOp v "SLte" ty [x, y]
456451doOp v (LEq (ATInt (ITFixed ty))) [x, y] = bitOp v "Eq" ty [x, y]
@@ -529,45 +524,56 @@ doOp v LFFloor [x] = v ++ flUnOp "floor" (creg x)
529524doOp v LFCeil [x] = v ++ flUnOp "ceil" (creg x)
530525doOp v LFNegate [x] = v ++ "MKFLOAT(vm, -GETFLOAT(" ++ (creg x) ++ "))"
531526
527+-- String functions which don't need to know we're UTF8
528+doOp v LStrConcat [l,r] = v ++ "idris_concat(vm, " ++ creg l ++ ", " ++ creg r ++ ")"
529+doOp v LStrLt [l,r] = v ++ "idris_strlt(vm, " ++ creg l ++ ", " ++ creg r ++ ")"
530+doOp v LStrEq [l,r] = v ++ "idris_streq(vm, " ++ creg l ++ ", " ++ creg r ++ ")"
531+
532+-- String functions which need to know we're UTF8
532533doOp v LStrHead [x] = v ++ "idris_strHead(vm, " ++ creg x ++ ")"
533534doOp v LStrTail [x] = v ++ "idris_strTail(vm, " ++ creg x ++ ")"
534535doOp v LStrCons [x, y] = v ++ "idris_strCons(vm, " ++ creg x ++ "," ++ creg y ++ ")"
535536doOp v LStrIndex [x, y] = v ++ "idris_strIndex(vm, " ++ creg x ++ "," ++ creg y ++ ")"
536537doOp v LStrRev [x] = v ++ "idris_strRev(vm, " ++ creg x ++ ")"
537−
538−doOp v LAllocate [x] = v ++ "idris_buffer_allocate(vm, " ++ creg x ++ ")"
539−doOp v LAppendBuffer [a, b, c, d, e, f] = v ++ "idris_appendBuffer(vm, " ++ creg a ++ "," ++ creg b ++ "," ++ creg c ++ "," ++ creg d ++ "," ++ creg e ++ "," ++ creg f ++ ")"
540−doOp v (LAppend ity en) [a, b, c, d] = v ++ "idris_append" ++ intTyName ity ++ show en ++ "(vm, " ++ creg a ++ "," ++ creg b ++ "," ++ creg c ++ "," ++ creg d ++ ")"
541−doOp v (LPeek ity en) [x, y] = v ++ "idris_peek" ++ intTyName ity ++ show en ++ "(vm, " ++ creg x ++ "," ++ creg y ++ ")"
542−
543−doOp v LStdIn [] = v ++ "MKPTR(vm, stdin)"
544−doOp v LStdOut [] = v ++ "MKPTR(vm, stdout)"
545−doOp v LStdErr [] = v ++ "MKPTR(vm, stderr)"
538+doOp v LStrLen [x] = v ++ "idris_strlen(vm, " ++ creg x ++ ")"
546539
547540doOp v LFork [x] = v ++ "MKPTR(vm, vmThread(vm, " ++ cname (sMN 0 "EVAL") ++ ", " ++ creg x ++ "))"
548541doOp v LPar [x] = v ++ creg x -- "MKPTR(vm, vmThread(vm, " ++ cname (MN 0 "EVAL") ++ ", " ++ creg x ++ "))"
549−doOp v LVMPtr [] = v ++ "MKPTR(vm, vm)"
550−doOp v LNullPtr [] = v ++ "MKPTR(vm, NULL)"
551−doOp v LRegisterPtr [p, i] = v ++ "MKMPTR(vm, GETPTR(" ++ creg p ++
552− "), GETINT(" ++ creg i ++ "))"
553542doOp v (LChInt ITNative) args = v ++ creg (last args)
554543doOp v (LChInt ITChar) args = doOp v (LChInt ITNative) args
555544doOp v (LIntCh ITNative) args = v ++ creg (last args)
556545doOp v (LIntCh ITChar) args = doOp v (LIntCh ITNative) args
557546
558−doOp v c@(LMkVec IT8 _) args = v ++ "MKB8x16(vm, " ++ (intercalate ", " (map creg args)) ++ ")"
559−doOp v c@(LMkVec IT16 _) args = v ++ "MKB16x8(vm, " ++ (intercalate ", " (map creg args)) ++ ")"
560−doOp v c@(LMkVec IT32 _) args = v ++ "MKB32x4(vm, " ++ (intercalate ", " (map creg args)) ++ ")"
561−doOp v c@(LMkVec IT64 _) args = v ++ "MKB64x2(vm, " ++ (intercalate ", " (map creg args)) ++ ")"
562−
563−doOp v c@(LIdxVec IT8 _) [p, i] = v ++ "idris_IDXB8x16(vm, " ++ creg p ++ ", " ++ creg i ++ ")"
564−doOp v c@(LIdxVec IT16 _) [p, i] = v ++ "idris_IDXB16x8(vm, " ++ creg p ++ ", " ++ creg i ++ ")"
565−doOp v c@(LIdxVec IT32 _) [p, i] = v ++ "idris_IDXB32x4(vm, " ++ creg p ++ ", " ++ creg i ++ ")"
566−doOp v c@(LIdxVec IT64 _) [p, i] = v ++ "idris_IDXB64x2(vm, " ++ creg p ++ ", " ++ creg i ++ ")"
567−
568547doOp v LSystemInfo [x] = v ++ "idris_systemInfo(vm, " ++ creg x ++ ")"
569548doOp v LNoOp args = v ++ creg (last args)
570−doOp _ op args = error "doOp of (" ++ show op ++ ") not implemented, arguments (" ++ show args ++ ")"
549+
550+-- Pointer primitives (declared as %extern in Builtins.idr)
551+doOp v (LExternal rs) [_]
552+ | rs == sUN "prim__readString" = v ++ "idris_readStr(vm, stdin)"
553+doOp v (LExternal ws) [_,s]
554+ | ws == sUN "prim__writeString"
555+ = v ++ "MKINT((i_int)(idris_writeStr(stdout"
556+ ++ ",GETSTR("
557+ ++ creg s ++ "))))"
558+
559+doOp v (LExternal rf) [_,x]
560+ | rf == sUN "prim__readFile"
561+ = v ++ "idris_readStr(vm, GETPTR(" ++ creg x ++ "))"
562+doOp v (LExternal wf) [_,x,s]
563+ | wf == sUN "prim__writeFile"
564+ = v ++ "MKINT((i_int)(idris_writeStr(GETPTR(" ++ creg x
565+ ++ "),GETSTR("
566+ ++ creg s ++ "))))"
567+doOp v (LExternal vm) [] | vm == sUN "prim__vm" = v ++ "MKPTR(vm, vm)"
568+doOp v (LExternal si) [] | si == sUN "prim__stdin" = v ++ "MKPTR(vm, stdin)"
569+doOp v (LExternal so) [] | so == sUN "prim__stdout" = v ++ "MKPTR(vm, stdout)"
570+doOp v (LExternal se) [] | se == sUN "prim__stderr" = v ++ "MKPTR(vm, stderr)"
571+
572+doOp v (LExternal nul) [] | nul == sUN "prim__null" = v ++ "MKPTR(vm, NULL)"
573+doOp v (LExternal rp) [p, i] | rp == sUN "prim__registerPtr"
574+ = v ++ "MKMPTR(vm, GETPTR(" ++ creg p ++ "), GETINT(" ++ creg i ++ "))"
575+
576+doOp _ op args = error $ "doOp not implemented (" ++ show (op, args) ++ ")"
571577
572578flUnOp :: String -> String -> String
573579flUnOp name val = "MKFLOAT(vm, " ++ name ++ "(GETFLOAT(" ++ val ++ ")))"
src/IRTS/CodegenJavaScript.hs+4−3
@@ -473,7 +473,6 @@ translateConstant StrType = JSType JSStringTy
473473translateConstant (AType (ATInt ITBig)) = JSType JSIntegerTy
474474translateConstant (AType ATFloat) = JSType JSFloatTy
475475translateConstant (AType (ATInt ITChar)) = JSType JSCharTy
476−translateConstant PtrType = JSType JSPtrTy
477476translateConstant Forgot = JSType JSForgotTy
478477translateConstant (BI 0) = JSNum (JSInteger JSBigZero)
479478translateConstant (BI 1) = JSNum (JSInteger JSBigOne)
@@ -680,7 +679,8 @@ jsOP _ reg op args = JSAssign (translateReg reg) jsOP'
680679 jsOP'
681680 | LNoOp <- op = translateReg (last args)
682681
683− | LWriteStr <- op,
682+ | (LExternal ws) <- op,
683+ ws == sUN "prim__writeString",
684684 (_:str:_) <- args = JSAssign (translateReg reg)
685685 (JSApp (JSIdent "i$putStr") [translateReg str])
686686
@@ -1269,7 +1269,8 @@ jsOP _ reg op args = JSAssign (translateReg reg) jsOP'
12691269
12701270 | LSystemInfo <- op
12711271 , (arg:_) <- args = jsCall "i$systemInfo" [translateReg arg]
1272− | LNullPtr <- op
1272+ | LExternal nul <- op
1273+ , nul == sUN "prim__null"
12731274 , (_) <- args = JSNull
12741275 | otherwise = JSError $ "Not implemented: " ++ show op
12751276 where
src/IRTS/Compiler.hs+14−3
@@ -185,7 +185,7 @@ isCon _ = False
185185build :: (Name, Def) -> Idris (Name, LDecl)
186186build (n, d)
187187 = do i <- getIState
188− case lookup n (idris_scprims i) of
188+ case getPrim n i of
189189 Just (ar, op) ->
190190 let args = map (\x -> sMN x "op") [0..] in
191191 return (n, (LFun [] n (take ar args)
@@ -193,6 +193,12 @@ build (n, d)
193193 _ -> do def <- mkLDecl n d
194194 logLvl 3 $ "Compiled " ++ show n ++ " =\n\t" ++ show def
195195 return (n, def)
196+ where getPrim n i
197+ | Just (ar, op) <- lookup n (idris_scprims i)
198+ = Just (ar, op)
199+ | Just ar <- lookup n (S.toList (idris_externs i))
200+ = Just (ar, LExternal n)
201+ getPrim n i = Nothing
196202
197203declArgs args inl n (LLam xs x) = declArgs (args ++ xs) inl n x
198204declArgs args inl n x = LFun (if inl then [Inline] else []) n args x
@@ -225,7 +231,9 @@ data VarInfo = VI
225231type Vars = M.Map Name VarInfo
226232
227233irTerm :: Vars -> [Name] -> Term -> Idris LExp
228−irTerm vs env tm@(App f a) = case unApply tm of
234+irTerm vs env tm@(App f a) = do
235+ ist <- getIState
236+ case unApply tm of
229237 (P _ (UN m) _, args)
230238 | m == txt "mkForeignPrim"
231239 -> doForeign vs env (reverse (drop 4 args)) -- drop implicits
@@ -359,9 +367,12 @@ irTerm vs env tm@(App f a) = case unApply tm of
359367 -- type constructor
360368 (P (TCon t a) n _, args) -> return LNothing
361369
370+ -- an external name applied to arguments
371+ (P _ n _, args) | S.member (n, length args) (idris_externs ist) -> do
372+ LOp (LExternal n) <$> mapM (irTerm vs env) args
373+
362374 -- a name applied to arguments
363375 (P _ n _, args) -> do
364− ist <- getIState
365376 case lookup n (idris_scprims ist) of
366377 -- if it's a primitive that is already saturated,
367378 -- compile to the corresponding op here already to save work
src/IRTS/Lang.hs+1−16
@@ -69,35 +69,20 @@ data PrimFn = LPlus ArithTy | LMinus ArithTy | LTimes ArithTy
6969 | LStrConcat | LStrLt | LStrEq | LStrLen
7070 | LIntFloat IntTy | LFloatInt IntTy | LIntStr IntTy | LStrInt IntTy
7171 | LFloatStr | LStrFloat | LChInt IntTy | LIntCh IntTy
72− | LReadStr | LWriteStr | LReadFile | LWriteFile
7372 | LBitCast ArithTy ArithTy -- Only for values of equal width
7473
7574 | LFExp | LFLog | LFSin | LFCos | LFTan | LFASin | LFACos | LFATan
7675 | LFSqrt | LFFloor | LFCeil | LFNegate
7776
78− -- construction element extraction element insertion
79− | LMkVec NativeTy Int | LIdxVec NativeTy Int | LUpdateVec NativeTy Int
80−
8177 | LStrHead | LStrTail | LStrCons | LStrIndex | LStrRev
82− | LStdIn | LStdOut | LStdErr
8378
84− -- Buffers
85− | LAllocate
86− | LAppendBuffer
8779 -- system info
8880 | LSystemInfo
89− -- Note that for Bits8 only Native endianness is actually used
90− -- and the user-exposed interface for Bits8 doesn't mention
91− -- endianness
92− | LAppend IntTy Endianness
93− | LPeek IntTy Endianness
9481
9582 | LFork
9683 | LPar -- evaluate argument anywhere, possibly on another
9784 -- core or another machine. 'id' is a valid implementation
98− | LVMPtr
99− | LNullPtr
100− | LRegisterPtr
85+ | LExternal Name
10186 | LNoOp
10287 deriving (Show, Eq)
10388
src/Idris/AbsSyntax.hs+12−15
@@ -543,10 +543,13 @@ addConstraints :: FC -> (Int, [UConstraint]) -> Idris ()
543543addConstraints fc (v, cs)
544544 = do i <- getIState
545545 let ctxt = tt_ctxt i
546− let ctxt' = ctxt { uconstraints = nub cs ++ uconstraints ctxt,
547− next_tvar = v }
548− let ics = zip cs (repeat fc) ++ idris_constraints i
546+ let ctxt' = ctxt { next_tvar = v }
547+ let ics = insertAll (zip cs (repeat fc)) (idris_constraints i)
549548 putIState $ i { tt_ctxt = ctxt', idris_constraints = ics }
549+ where
550+ insertAll [] c = c
551+ insertAll ((c, fc) : cs) ics
552+ = insertAll cs $ S.insert (ConstraintFC c fc) ics
550553
551554addDeferred = addDeferred' Ref
552555addDeferredTyCon = addDeferred' (TCon 0 0)
@@ -606,12 +609,6 @@ setWidth :: ConsoleWidth -> Idris ()
606609setWidth w = do ist <- getIState
607610 put ist { idris_consolewidth = w }
608611
609−renderWidth :: Idris Int
610−renderWidth = do iw <- getWidth
611− case iw of
612− InfinitelyWide -> return 100000000
613− ColsWide n -> return (max n 1)
614− AutomaticWidth -> runIO getScreenWidth
615612
616613
617614
@@ -1016,13 +1013,13 @@ expandParamsD rhsonly ist dec ps ns (PTy doc argdocs syn fc o n ty)
10161013 PTy doc argdocs syn fc o (dec n) (piBindp expl_param ps (expandParams dec ps ns [] ty))
10171014 else --trace (show (n, expandParams dec ps ns ty)) $
10181015 PTy doc argdocs syn fc o n (expandParams dec ps ns [] ty)
1019−expandParamsD rhsonly ist dec ps ns (PPostulate doc syn fc o n ty)
1016+expandParamsD rhsonly ist dec ps ns (PPostulate e doc syn fc o n ty)
10201017 = if n `elem` ns && (not rhsonly)
10211018 then -- trace (show (n, expandParams dec ps ns ty)) $
1022− PPostulate doc syn fc o (dec n) (piBind ps
1019+ PPostulate e doc syn fc o (dec n) (piBind ps
10231020 (expandParams dec ps ns [] ty))
10241021 else --trace (show (n, expandParams dec ps ns ty)) $
1025− PPostulate doc syn fc o n (expandParams dec ps ns [] ty)
1022+ PPostulate e doc syn fc o n (expandParams dec ps ns [] ty)
10261023expandParamsD rhsonly ist dec ps ns (PClauses fc opts n cs)
10271024 = let n' = if n `elem` ns then dec n else n in
10281025 PClauses fc opts n' (map expandParamsC cs)
@@ -1686,9 +1683,9 @@ aiFn inpat expat qq imp_meths ist fc f ds as
16861683 case find n imps [] of
16871684 Just (tm, imps') ->
16881685 PImp p False l n tm : insImpAcc (M.insert n tm pnas) ps given imps'
1689− Nothing ->
1690− PImp p True l n Placeholder :
1691− insImpAcc (M.insert n Placeholder pnas) ps given imps
1686+ Nothing -> let ph = if f `elem` imp_meths then PRef fc n else Placeholder in
1687+ PImp p True l n ph :
1688+ insImpAcc (M.insert n ph pnas) ps given imps
16921689 insImpAcc pnas (PTacImplicit p l n sc' ty : ps) given imps =
16931690 let sc = addImpl imp_meths ist (substMatches (M.toList pnas) sc') in
16941691 case find n imps [] of
src/Idris/AbsSyntaxTree.hs+34−28
@@ -66,27 +66,27 @@ toplevel = EInfo [] emptyContext id Nothing Nothing (\_ _ _ -> fail "Not impleme
6666eInfoNames :: ElabInfo -> [Name]
6767eInfoNames info = map fst (params info) ++ M.keys (inblock info)
6868
69−data IOption = IOption { opt_logLevel :: Int,
70− opt_typecase :: Bool,
71− opt_typeintype :: Bool,
72− opt_coverage :: Bool,
73− opt_showimp :: Bool, -- ^^ show implicits
74− opt_errContext :: Bool,
75− opt_repl :: Bool,
76− opt_verbose :: Bool,
77− opt_nobanner :: Bool,
78− opt_quiet :: Bool,
79− opt_codegen :: Codegen,
80− opt_outputTy :: OutputType,
81− opt_ibcsubdir :: FilePath,
82− opt_importdirs :: [FilePath],
83− opt_triple :: String,
84− opt_cpu :: String,
85− opt_cmdline :: [Opt], -- remember whole command line
86− opt_origerr :: Bool,
87− opt_autoSolve :: Bool, -- ^ automatically apply "solve" tactic in prover
88− opt_autoImport :: [FilePath], -- ^ e.g. Builtins+Prelude
89− opt_optimise :: [Optimisation]
69+data IOption = IOption { opt_logLevel :: Int,
70+ opt_typecase :: Bool,
71+ opt_typeintype :: Bool,
72+ opt_coverage :: Bool,
73+ opt_showimp :: Bool, -- ^^ show implicits
74+ opt_errContext :: Bool,
75+ opt_repl :: Bool,
76+ opt_verbose :: Bool,
77+ opt_nobanner :: Bool,
78+ opt_quiet :: Bool,
79+ opt_codegen :: Codegen,
80+ opt_outputTy :: OutputType,
81+ opt_ibcsubdir :: FilePath,
82+ opt_importdirs :: [FilePath],
83+ opt_triple :: String,
84+ opt_cpu :: String,
85+ opt_cmdline :: [Opt], -- remember whole command line
86+ opt_origerr :: Bool,
87+ opt_autoSolve :: Bool, -- ^ automatically apply "solve" tactic in prover
88+ opt_autoImport :: [FilePath], -- ^ e.g. Builtins+Prelude
89+ opt_optimise :: [Optimisation]
9090 }
9191 deriving (Show, Eq)
9292
@@ -151,11 +151,13 @@ data OutputMode = RawOutput Handle -- ^ Print user output directly to the handle
151151data ConsoleWidth = InfinitelyWide -- ^ Have pretty-printer assume that lines should not be broken
152152 | ColsWide Int -- ^ Manually specified - must be positive
153153 | AutomaticWidth -- ^ Attempt to determine width, or 80 otherwise
154+ deriving (Show, Eq)
155+
154156
155157-- | The global state used in the Idris monad
156158data IState = IState {
157159 tt_ctxt :: Context, -- ^ All the currently defined names and their terms
158− idris_constraints :: [(UConstraint, FC)],
160+ idris_constraints :: S.Set ConstraintFC,
159161 -- ^ A list of universe constraints and their corresponding source locations
160162 idris_infixes :: [FixDecl], -- ^ Currently defined infix operators
161163 idris_implicits :: Ctxt [PArg],
@@ -224,6 +226,7 @@ data IState = IState {
224226 module_aliases :: M.Map [T.Text] [T.Text],
225227 idris_consolewidth :: ConsoleWidth, -- ^ How many chars wide is the console?
226228 idris_postulates :: S.Set Name,
229+ idris_externs :: S.Set (Name, Int),
227230 idris_erasureUsed :: [(Name, Int)], -- ^ Function/constructor name, argument position is used
228231 idris_whocalls :: Maybe (M.Map Name [Name]),
229232 idris_callswho :: Maybe (M.Map Name [Name]),
@@ -298,6 +301,7 @@ data IBCWrite = IBCFix FixDecl
298301 | IBCErrorHandler Name
299302 | IBCFunctionErrorHandler Name Name Name
300303 | IBCPostulate Name
304+ | IBCExtern (Name, Int)
301305 | IBCTotCheckErr FC String
302306 | IBCParsedRegion FC
303307 | IBCModDocs Name -- ^ The name is the special name used to track module docs
@@ -307,7 +311,7 @@ data IBCWrite = IBCFix FixDecl
307311
308312-- | The initial state for the compiler
309313idrisInit :: IState
310−idrisInit = IState initContext [] []
314+idrisInit = IState initContext S.empty []
311315 emptyContext emptyContext emptyContext emptyContext
312316 emptyContext emptyContext emptyContext emptyContext
313317 emptyContext emptyContext emptyContext emptyContext
@@ -315,7 +319,7 @@ idrisInit = IState initContext [] []
315319 [] [] [] defaultOpts 6 [] [] [] [] emptySyntaxRules [] [] [] [] [] [] []
316320 [] [] Nothing [] Nothing [] [] Nothing Nothing [] Hidden False [] Nothing [] []
317321 (RawOutput stdout) True defaultTheme [] (0, emptyContext) emptyContext M.empty
318− AutomaticWidth S.empty [] Nothing Nothing [] [] M.empty []
322+ AutomaticWidth S.empty S.empty [] Nothing Nothing [] [] M.empty []
319323
320324-- | The monad for the main REPL - reading and processing files and updating
321325-- global state (hence the IO inner monad).
@@ -467,6 +471,7 @@ data Opt = Filename String
467471 | ShowOrigErr
468472 | AutoWidth -- ^ Automatically adjust terminal width
469473 | AutoSolve -- ^ Automatically issue "solve" tactic in interactive prover
474+ | UseConsoleWidth ConsoleWidth
470475 deriving (Show, Eq)
471476
472477-- Parsed declarations
@@ -590,7 +595,8 @@ type ProvideWhat = ProvideWhat' PTerm
590595data PDecl' t
591596 = PFix FC Fixity [String] -- ^ Fixity declaration
592597 | PTy (Docstring (Either Err PTerm)) [(Name, Docstring (Either Err PTerm))] SyntaxInfo FC FnOpts Name t -- ^ Type declaration
593− | PPostulate (Docstring (Either Err PTerm)) SyntaxInfo FC FnOpts Name t -- ^ Postulate
598+ | PPostulate Bool -- external def if true
599+ (Docstring (Either Err PTerm)) SyntaxInfo FC FnOpts Name t -- ^ Postulate
594600 | PClauses FC FnOpts Name [PClause' t] -- ^ Pattern clause
595601 | PCAF FC Name t -- ^ Top level constant
596602 | PData (Docstring (Either Err PTerm)) [(Name, Docstring (Either Err PTerm))] SyntaxInfo FC DataOpts (PData' t) -- ^ Data declaration.
@@ -698,7 +704,7 @@ type PClause = PClause' PTerm
698704declared :: PDecl -> [Name]
699705declared (PFix _ _ _) = []
700706declared (PTy _ _ _ _ _ n t) = [n]
701−declared (PPostulate _ _ _ _ n t) = [n]
707+declared (PPostulate _ _ _ _ _ n t) = [n]
702708declared (PClauses _ _ n _) = [] -- not a declaration
703709declared (PCAF _ n _) = [n]
704710declared (PData _ _ _ _ _ (PDatadecl n _ ts)) = n : map fstt ts
@@ -719,7 +725,7 @@ declared _ = []
719725tldeclared :: PDecl -> [Name]
720726tldeclared (PFix _ _ _) = []
721727tldeclared (PTy _ _ _ _ _ n t) = [n]
722−tldeclared (PPostulate _ _ _ _ n t) = [n]
728+tldeclared (PPostulate _ _ _ _ _ n t) = [n]
723729tldeclared (PClauses _ _ n _) = [] -- not a declaration
724730tldeclared (PRecord _ _ _ _ n _ _ _ cn _ _) = n : maybeToList cn
725731tldeclared (PData _ _ _ _ _ (PDatadecl n _ ts)) = n : map fstt ts
@@ -734,7 +740,7 @@ tldeclared _ = []
734740defined :: PDecl -> [Name]
735741defined (PFix _ _ _) = []
736742defined (PTy _ _ _ _ _ n t) = []
737−defined (PPostulate _ _ _ _ n t) = []
743+defined (PPostulate _ _ _ _ _ n t) = []
738744defined (PClauses _ _ n _) = [n] -- not a declaration
739745defined (PCAF _ n _) = [n]
740746defined (PData _ _ _ _ _ (PDatadecl n _ ts)) = n : map fstt ts
src/Idris/CmdOptions.hs+30
@@ -11,6 +11,12 @@ import Options.Applicative.Arrows
1111import Data.Char
1212import Data.Maybe
1313
14+import Text.ParserCombinators.ReadP hiding (many, option)
15+
16+import Safe (lastMay)
17+
18+
19+
1420import qualified Text.PrettyPrint.ANSI.Leijen as PP
1521
1622runArgParser :: IO [Opt]
@@ -67,6 +73,7 @@ parser = runA $ proc () -> do
6773 files <- asA (many $ argument (fmap Filename str) (metavar "FILES")) -< ()
6874 A parseVersion >>> A helper -< (flags ++ files)
6975
76+
7077parseFlags :: Parser [Opt]
7178parseFlags = many $
7279 flag' NoBanner (long "nobanner" <> help "Suppress the banner")
@@ -132,6 +139,10 @@ parseFlags = many $
132139 <|> (TargetCPU <$> strOption (long "cpu" <> metavar "CPU" <> help "Select target CPU e.g. corei7 or cortex-m3 (for LLVM codegen)"))
133140 <|> flag' (ColourREPL True) (long "colour" <> long "color" <> help "Force coloured output")
134141 <|> flag' (ColourREPL False) (long "nocolour" <> long "nocolor" <> help "Disable coloured output")
142+
143+ <|> (UseConsoleWidth <$> option (str >>= parseConsoleWidth) (long "consolewidth" <> metavar "WIDTH" <> help "Select console width: auto, infinite, nat"))
144+
145+
135146 where
136147 getExt s = case maybeRead s of
137148 Just ext -> ext
@@ -151,3 +162,22 @@ preProcOpts (x:xs) ys = preProcOpts xs (x:ys)
151162parseCodegen :: String -> Codegen
152163parseCodegen "bytecode" = Bytecode
153164parseCodegen cg = Via (map toLower cg)
165+
166+
167+
168+
169+parseConsoleWidth :: Monad m => String -> m ConsoleWidth
170+parseConsoleWidth "auto" = return AutomaticWidth
171+parseConsoleWidth "infinite" = return InfinitelyWide
172+parseConsoleWidth s =
173+ case lastMay (readP_to_S (integerReader) s) of
174+ Just (r, _) -> return $ ColsWide r
175+ _ -> fail $ "Cannot parse: " ++ s
176+
177+
178+
179+integerReader :: ReadP Int
180+integerReader = do
181+ digits <- many1 $ satisfy isDigit
182+ return $ read digits
183+
src/Idris/Core/Binary.hs+16−25
@@ -342,20 +342,8 @@ instance Binary Const where
342342 (AType ATFloat) -> putWord8 11
343343 (AType (ATInt ITChar)) -> putWord8 12
344344 StrType -> putWord8 13
345− PtrType -> putWord8 14
346345 Forgot -> putWord8 15
347346 (AType (ATInt (ITFixed ity))) -> putWord8 (fromIntegral (16 + fromEnum ity)) -- 16-19 inclusive
348− (AType (ATInt (ITVec ity count))) -> do
349− putWord8 20
350− putWord8 (fromIntegral . fromEnum $ ity)
351− putWord8 (fromIntegral count)
352−
353− B8V x1 -> putWord8 21 >> put x1
354− B16V x1 -> putWord8 22 >> put x1
355− B32V x1 -> putWord8 23 >> put x1
356− B64V x1 -> putWord8 24 >> put x1
357− BufferType -> putWord8 25
358− ManagedPtrType -> putWord8 26
359347 VoidType -> putWord8 27
360348 WorldType -> putWord8 28
361349 TheWorld -> putWord8 29
@@ -382,7 +370,6 @@ instance Binary Const where
382370 11 -> return (AType ATFloat)
383371 12 -> return (AType (ATInt ITChar))
384372 13 -> return StrType
385− 14 -> return PtrType
386373 15 -> return Forgot
387374
388375 16 -> return (AType (ATInt (ITFixed IT8)))
@@ -390,17 +377,6 @@ instance Binary Const where
390377 18 -> return (AType (ATInt (ITFixed IT32)))
391378 19 -> return (AType (ATInt (ITFixed IT64)))
392379
393− 20 -> do
394− e <- getWord8
395− c <- getWord8
396− return (AType (ATInt (ITVec (toEnum . fromIntegral $ e) (fromIntegral c))))
397−
398− 21 -> fmap B8V get
399− 22 -> fmap B16V get
400− 23 -> fmap B32V get
401− 24 -> fmap B64V get
402− 25 -> return BufferType
403− 26 -> return ManagedPtrType
404380 27 -> return VoidType
405381 28 -> return WorldType
406382 29 -> return TheWorld
@@ -546,6 +522,21 @@ instance Binary NameType where
546522 return (TCon (x1x2 `div` 65536) (x1x2 `mod` 65536))
547523 _ -> error "Corrupted binary data for NameType"
548524
525+-- record concrete levels only, for now
526+instance Binary UExp where
527+ put x = case x of
528+ UVar t -> do putWord8 0
529+ put ((-1) :: Int) -- TMP HACK!
530+ UVal t -> do putWord8 1
531+ put t
532+
533+ get = do i <- getWord8
534+ case i of
535+ 0 -> do x1 <- get
536+ return (UVar x1)
537+ 1 -> do x1 <- get
538+ return (UVal x1)
539+ _ -> error "Corrupted binary data for UExp"
549540
550541instance {- (Binary n) => -} Binary (TT Name) where
551542 put x
@@ -600,7 +591,7 @@ instance {- (Binary n) => -} Binary (TT Name) where
600591 x2 <- getWord8
601592 return (Proj x1 ((fromEnum x2)-1))
602593 6 -> return Erased
603− 7 -> do x1 <- get
594+ 7 -> do x1 <- get
604595 return (TType x1)
605596 8 -> return Impossible
606597 9 -> do x1 <- get
src/Idris/Core/CaseTree.hs−4
@@ -321,10 +321,6 @@ isConstType (B8 _) (AType (ATInt _)) = True
321321isConstType (B16 _) (AType (ATInt _)) = True
322322isConstType (B32 _) (AType (ATInt _)) = True
323323isConstType (B64 _) (AType (ATInt _)) = True
324−isConstType (B8V _) (AType (ATInt _)) = True
325−isConstType (B16V _) (AType (ATInt _)) = True
326−isConstType (B32V _) (AType (ATInt _)) = True
327−isConstType (B64V _) (AType (ATInt _)) = True
328324isConstType _ _ = False
329325
330326data Pat = PCon Bool Name Int [Pat]
src/Idris/Core/Constraints.hs+212−60
@@ -1,71 +1,223 @@
11-- | Check universe constraints.
2−module Idris.Core.Constraints(ucheck) where
2+module Idris.Core.Constraints ( ucheck ) where
33
4−import Idris.Core.TT
5−import Idris.Core.Typecheck
4+import Idris.Core.TT ( TC(..), UExp(..), UConstraint(..), FC(..),
5+ ConstraintFC(..), Err'(..) )
66
77import Control.Applicative
8−import Control.Arrow
9−import Control.Monad.RWS
10−import Control.Monad.State
11−import qualified Data.Set as S
12−import Data.List
13−import Data.Maybe
8+import Control.Monad.State.Strict
9+import Data.List ( partition )
1410import qualified Data.Map.Strict as M
11+import qualified Data.Set as S
1512
16−import Debug.Trace
1713
1814-- | Check that a list of universe constraints can be satisfied.
19−ucheck :: [(UConstraint, FC)] -> TC ()
20−ucheck cs = acyclic rels (map fst (M.toList rels))
21− where lhs (ULT l _) = l
22− lhs (ULE l _) = l
23− cs' = S.toList (S.fromList cs)
24− rels = mkRels cs' M.empty
25−
26−type Relations = M.Map UExp [(UConstraint, FC)]
27−
28−mkRels :: [(UConstraint, FC)] -> Relations -> Relations
29−mkRels [] acc = acc
30−mkRels ((c, f) : cs) acc
31− | not (ignore c)
32− = case M.lookup (lhs c) acc of
33− Nothing -> mkRels cs (M.insert (lhs c) [(c,f)] acc)
34− Just rs -> mkRels cs (M.insert (lhs c) ((c,f):rs) acc)
35− | otherwise = mkRels cs acc
36− where lhs (ULT l _) = l
37− lhs (ULE l _) = l
38− ignore (ULE l r) = l == r
15+ucheck :: S.Set ConstraintFC -> TC ()
16+ucheck = void . solve 10 . S.filter (not . ignore)
17+ where
18+ -- TODO: remove the first ignore clause once Idris.Core.Binary:598 is dealt with
19+ ignore (ConstraintFC c _) | any (== Var (-1)) (varsIn c) = True
20+ ignore (ConstraintFC (ULE a b) _) = a == b
3921 ignore _ = False
4022
23+newtype Var = Var Int
24+ deriving (Eq, Ord, Show)
25+
26+data Domain = Domain Int Int
27+ deriving (Eq, Ord, Show)
28+
29+data SolverState =
30+ SolverState
31+ { queue :: Queue
32+ , domainStore :: M.Map Var ( Domain
33+ , S.Set ConstraintFC -- constraints that effected this variable
34+ )
35+ , cons_lhs :: M.Map Var (S.Set ConstraintFC)
36+ , cons_rhs :: M.Map Var (S.Set ConstraintFC)
37+ }
38+
39+data Queue = Queue [ConstraintFC] (S.Set UConstraint)
40+
41+
42+solve :: Int -> S.Set ConstraintFC -> TC (M.Map Var Int)
43+solve maxUniverseLevel ucs =
44+ evalStateT (propagate >> extractSolution) initSolverState
45+
46+ where
47+ inpConstraints = S.toAscList ucs
48+
49+ -- | initial solver state.
50+ -- the queue contains all constraints, the domain store contains the initial domains.
51+ initSolverState :: SolverState
52+ initSolverState =
53+ let
54+ (initUnaryQueue, initQueue) = partition (\ c -> length (varsIn (uconstraint c)) == 1) inpConstraints
55+ in
56+ SolverState
57+ { queue = Queue (initUnaryQueue ++ initQueue) (S.fromList (map uconstraint (initUnaryQueue ++ initQueue)))
58+ , domainStore = M.fromList
59+ [ (v, (Domain 0 maxUniverseLevel, S.empty))
60+ | v <- ordNub [ v
61+ | ConstraintFC c _ <- inpConstraints
62+ , v <- varsIn c
63+ ]
64+ ]
65+ , cons_lhs = constraintsLHS
66+ , cons_rhs = constraintsRHS
67+ }
68+
69+ lhs (ULT (UVar x) _) = Just (Var x)
70+ lhs (ULE (UVar x) _) = Just (Var x)
71+ lhs _ = Nothing
72+
73+ rhs (ULT _ (UVar x)) = Just (Var x)
74+ rhs (ULE _ (UVar x)) = Just (Var x)
75+ rhs _ = Nothing
76+
77+ -- | a map from variables to the list of constraints the variable occurs in. (in the LHS of a constraint)
78+ constraintsLHS :: M.Map Var (S.Set ConstraintFC)
79+ constraintsLHS = M.fromListWith S.union
80+ [ (v, S.singleton (ConstraintFC c fc))
81+ | (ConstraintFC c fc) <- inpConstraints
82+ , let vars = varsIn c
83+ , length vars > 1 -- do not register unary constraints
84+ , v <- vars
85+ , lhs c == Just v
86+ ]
87+
88+ -- | a map from variables to the list of constraints the variable occurs in. (in the RHS of a constraint)
89+ constraintsRHS :: M.Map Var (S.Set ConstraintFC)
90+ constraintsRHS = M.fromListWith S.union
91+ [ (v, S.singleton (ConstraintFC c fc))
92+ | (ConstraintFC c fc) <- inpConstraints
93+ , let vars = varsIn c
94+ , length vars > 1 -- do not register unary constraints
95+ , v <- vars
96+ , rhs c == Just v
97+ ]
98+
99+ -- | this is where the actual work is done.
100+ -- dequeue the first constraint,
101+ -- filter domains,
102+ -- update domains (possibly resulting in a domain wipe out),
103+ -- until the queue is empty.
104+ propagate :: StateT SolverState TC ()
105+ propagate = do
106+ mcons <- nextConstraint
107+ case mcons of
108+ Nothing -> return ()
109+ Just (ConstraintFC cons fc) -> do
110+ case cons of
111+ ULE a b -> do
112+ Domain lowerA upperA <- domainOf a
113+ Domain lowerB upperB <- domainOf b
114+ when (upperB < upperA) $ updateUpperBoundOf (ConstraintFC cons fc) a upperB
115+ when (lowerA > lowerB) $ updateLowerBoundOf (ConstraintFC cons fc) b lowerA
116+ ULT a b -> do
117+ Domain lowerA upperA <- domainOf a
118+ Domain lowerB upperB <- domainOf b
119+ let upperB_pred = pred upperB
120+ let lowerA_succ = succ lowerA
121+ when (upperB_pred < upperA) $ updateUpperBoundOf (ConstraintFC cons fc) a upperB_pred
122+ when (lowerA_succ > lowerB) $ updateLowerBoundOf (ConstraintFC cons fc) b lowerA_succ
123+ propagate
124+
125+ -- | extract a solution from the state.
126+ extractSolution :: (MonadState SolverState m, Functor m) => m (M.Map Var Int)
127+ extractSolution = M.map (extractValue . fst) <$> gets domainStore
128+
129+ extractValue :: Domain -> Int
130+ extractValue (Domain x _) = x
131+
132+ -- | dequeue the first constraint.
133+ nextConstraint :: MonadState SolverState m => m (Maybe ConstraintFC)
134+ nextConstraint = do
135+ Queue list set <- gets queue
136+ case list of
137+ [] -> return Nothing
138+ (q:qs) -> do
139+ modify $ \ st -> st { queue = Queue qs (S.delete (uconstraint q) set) }
140+ return (Just q)
141+
142+ -- | look up the domain of a variable from the state.
143+ -- for convenience, this function also accepts UVal's and returns a singleton domain for them.
144+ domainOf :: MonadState SolverState m => UExp -> m Domain
145+ domainOf (UVar var) = gets (fst . (M.! Var var) . domainStore)
146+ domainOf (UVal val) = return (Domain val val)
147+
148+ updateUpperBoundOf :: ConstraintFC -> UExp -> Int -> StateT SolverState TC ()
149+ updateUpperBoundOf suspect (UVar var) upper = do
150+ doms <- gets domainStore
151+ let (oldDom@(Domain lower _), suspects) = doms M.! Var var
152+ let newDom = Domain lower upper
153+ when (wipeOut newDom) $ lift $ Error $ At (ufc suspect) $ Msg $ unlines
154+ $ "Universe inconsistency."
155+ : ("Working on: " ++ show (UVar var))
156+ : ("Old domain: " ++ show oldDom)
157+ : ("New domain: " ++ show newDom)
158+ : "Involved constraints: "
159+ : map (("\t"++) . show) (suspect : S.toList suspects)
160+ modify $ \ st -> st { domainStore = M.insert (Var var) (newDom, S.insert suspect suspects) doms }
161+ addToQueueRHS (uconstraint suspect) (Var var)
162+ updateUpperBoundOf _ UVal{} _ = return ()
163+
164+ updateLowerBoundOf :: ConstraintFC -> UExp -> Int -> StateT SolverState TC ()
165+ updateLowerBoundOf suspect (UVar var) lower = do
166+ doms <- gets domainStore
167+ let (oldDom@(Domain _ upper), suspects) = doms M.! Var var
168+ let newDom = Domain lower upper
169+ when (wipeOut newDom) $ lift $ Error $ At (ufc suspect) $ Msg $ unlines
170+ $ "Universe inconsistency."
171+ : ("Working on: " ++ show (UVar var))
172+ : ("Old domain: " ++ show oldDom)
173+ : ("New domain: " ++ show newDom)
174+ : "Involved constraints: "
175+ : map (("\t"++) . show) (suspect : S.toList suspects)
176+ modify $ \ st -> st { domainStore = M.insert (Var var) (newDom, S.insert suspect suspects) doms }
177+ addToQueueLHS (uconstraint suspect) (Var var)
178+ updateLowerBoundOf _ UVal{} _ = return ()
179+
180+ -- | add all constraints (with the given var on the lhs) to the queue
181+ addToQueueLHS :: MonadState SolverState m => UConstraint -> Var -> m ()
182+ addToQueueLHS thisCons var = do
183+ clhs <- gets cons_lhs
184+ case M.lookup var clhs of
185+ Nothing -> return ()
186+ Just cs -> do
187+ Queue list set <- gets queue
188+ let set' = S.insert thisCons set
189+ let newCons = [ c | c <- S.toList cs, uconstraint c `S.notMember` set' ]
190+ if null newCons
191+ then return ()
192+ else modify $ \ st -> st { queue = Queue (list ++ newCons)
193+ (S.union set (S.fromList (map uconstraint newCons))) }
194+
195+ -- | add all constraints (with the given var on the rhs) to the queue
196+ addToQueueRHS :: MonadState SolverState m => UConstraint -> Var -> m ()
197+ addToQueueRHS thisCons var = do
198+ crhs <- gets cons_rhs
199+ case M.lookup var crhs of
200+ Nothing -> return ()
201+ Just cs -> do
202+ Queue list set <- gets queue
203+ let set' = S.insert thisCons set
204+ let newCons = [ c | c <- S.toList cs, uconstraint c `S.notMember` set' ]
205+ if null newCons
206+ then return ()
207+ else modify $ \ st -> st { queue = Queue (list ++ newCons)
208+ (insertAll (map uconstraint newCons) set) }
209+
210+ insertAll [] s = s
211+ insertAll (x : xs) s = insertAll xs (S.insert x s)
212+
213+ -- | check if a domain is wiped out.
214+ wipeOut :: Domain -> Bool
215+ wipeOut (Domain l u) = l > u
216+
217+ordNub :: Ord a => [a] -> [a]
218+ordNub = S.toList . S.fromList
41219
42−acyclic :: Relations -> [UExp] -> TC ()
43−acyclic r cvs = checkCycle (fileFC "root") r [] 0 cvs
44− where
45− checkCycle :: FC -> Relations -> [(UExp, FC)] -> Int -> [UExp] -> TC ()
46− checkCycle fc r path inc [] = return ()
47− checkCycle fc r path inc (c : cs)
48− = do check fc r path inc c
49− -- Remove c from r since we know there's no cycles now
50− let r' = M.insert c [] r
51− checkCycle fc r' path inc cs
52−
53− check fc r path inc (UVar x) | x < 0 = return ()
54− check fc r path inc cv
55− | inc > 0 && cv `elem` map fst path
56− = Error $ At fc UniverseError
57− -- FIXME: Make informative
58− -- e.g. (Msg ("Cycle: " ++ show cv ++ ", " ++ show path))
59− -- Issue #1725 on the issue tracker.
60− -- https://github.com/idris-lang/Idris-dev/issues/1725
61− -- if we reach a cycle but we're at the same universe level, it's
62− -- fine, because they must all be equal, so stop.
63− | inc == 0 && cv `elem` map fst path
64− = return ()
65− | otherwise
66− = case M.lookup cv r of
67− Nothing -> return ()
68− Just cs -> mapM_ (next r ((cv, fc):path) inc) cs
69−
70− next r path inc (ULT l x, fc) = check fc r path (inc + 1) x
71− next r path inc (ULE l x, fc) = check fc r path inc x
220+-- | variables in a constraint
221+varsIn :: UConstraint -> [Var]
222+varsIn (ULT a b) = [ Var v | UVar v <- [a,b] ]
223+varsIn (ULE a b) = [ Var v | UVar v <- [a,b] ]
src/Idris/Core/DeepSeq.hs−8
@@ -134,7 +134,6 @@ instance NFData IntTy where
134134 rnf ITNative = ()
135135 rnf ITBig = ()
136136 rnf ITChar = ()
137− rnf (ITVec x1 x2) = rnf x1 `seq` rnf x2 `seq` ()
138137
139138instance NFData ArithTy where
140139 rnf (ATInt x1) = rnf x1 `seq` ()
@@ -150,17 +149,10 @@ instance NFData Const where
150149 rnf (B16 x1) = rnf x1 `seq` ()
151150 rnf (B32 x1) = rnf x1 `seq` ()
152151 rnf (B64 x1) = rnf x1 `seq` ()
153− rnf (B8V x1) = rnf x1 `seq` ()
154− rnf (B16V x1) = rnf x1 `seq` ()
155− rnf (B32V x1) = rnf x1 `seq` ()
156− rnf (B64V x1) = rnf x1 `seq` ()
157152 rnf (AType x1) = rnf x1 `seq` ()
158153 rnf WorldType = ()
159154 rnf TheWorld = ()
160155 rnf StrType = ()
161− rnf PtrType = ()
162− rnf ManagedPtrType = ()
163− rnf BufferType = ()
164156 rnf VoidType = ()
165157 rnf Forgot = ()
166158
src/Idris/Core/Evaluate.hs+3−7
@@ -5,7 +5,7 @@ module Idris.Core.Evaluate(normalise, normaliseTrace, normaliseC, normaliseAll,
55 rt_simplify, simplify, specialise, hnf, convEq, convEq',
66 Def(..), CaseInfo(..), CaseDefs(..),
77 Accessibility(..), Totality(..), PReason(..), MetaInformation(..),
8− Context, initContext, ctxtAlist, uconstraints, next_tvar,
8+ Context, initContext, ctxtAlist, next_tvar,
99 addToCtxt, setAccess, setTotal, setMetaInformation, addCtxtDef, addTyDecl,
1010 addDatatype, addCasedef, simplifyCasedef, addOperator,
1111 lookupNames, lookupTyName, lookupTyNameExact, lookupTy, lookupTyExact,
@@ -502,12 +502,9 @@ eval traceon ctxt ntimes genv tm opts = ev ntimes [] True [] tm where
502502 findConst (AType ATFloat) (ConCase n 2 [] v : xs) = Just v
503503 findConst (AType (ATInt ITChar)) (ConCase n 3 [] v : xs) = Just v
504504 findConst StrType (ConCase n 4 [] v : xs) = Just v
505− findConst PtrType (ConCase n 5 [] v : xs) = Just v
506505 findConst (AType (ATInt ITBig)) (ConCase n 6 [] v : xs) = Just v
507506 findConst (AType (ATInt (ITFixed ity))) (ConCase n tag [] v : xs)
508507 | tag == 7 + fromEnum ity = Just v
509− findConst (AType (ATInt (ITVec ity count))) (ConCase n tag [] v : xs)
510− | tag == (fromEnum ity + 1) * 1000 + count = Just v
511508 findConst c (_ : xs) = findConst c xs
512509
513510 getValArgs tm = getValArgs' tm []
@@ -786,16 +783,15 @@ data MetaInformation =
786783-- | Contexts used for global definitions and for proof state. They contain
787784-- universe constraints and existing definitions.
788785data Context = MkContext {
789− uconstraints :: [UConstraint],
790786 next_tvar :: Int,
791787 definitions :: Ctxt (Def, Accessibility, Totality, MetaInformation)
792788 } deriving Show
793789
794790-- | The initial empty context
795−initContext = MkContext [] 0 emptyContext
791+initContext = MkContext 0 emptyContext
796792
797793mapDefCtxt :: (Def -> Def) -> Context -> Context
798−mapDefCtxt f (MkContext c t defs) = MkContext c t (mapCtxt f' defs)
794+mapDefCtxt f (MkContext t defs) = MkContext t (mapCtxt f' defs)
799795 where f' (d, a, t, m) = f' (f d, a, t, m)
800796
801797-- | Get the definitions from a context
src/Idris/Core/Execute.hs+47−41
@@ -1,4 +1,5 @@
11{-# LANGUAGE PatternGuards, ExistentialQuantification, CPP #-}
2+{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
23module Idris.Core.Execute (execute) where
34
45import Idris.AbsSyntax
@@ -111,7 +112,8 @@ toTT (EThunk ctxt env tm) = do env' <- mapM toBinder env
111112 return $ normalise ctxt env' tm
112113 where toBinder (n, v) = do v' <- toTT v
113114 return (n, Let Erased v')
114−toTT (EHandle _) = return Erased
115+toTT (EHandle _) = execFail $ Msg "Can't convert handles back to TT after execution."
116+toTT (EPtr ptr) = execFail $ Msg "Can't convert pointers back to TT after execution."
115117
116118unApplyV :: ExecVal -> (ExecVal, [ExecVal])
117119unApplyV tm = ua [] tm
@@ -249,6 +251,9 @@ execApp env ctxt c@(EP (TCon _ arity) n _) args =
249251 let restArgs = drop arity args
250252 execApp env ctxt (mkEApp c args') restArgs
251253
254+execApp env ctxt f@(EP _ n _) args
255+ | Just (res, rest) <- getOp n args = do r <- res
256+ execApp env ctxt r rest
252257execApp env ctxt f@(EP _ n _) args =
253258 do let val = lookupDef n ctxt
254259 case val of
@@ -258,9 +263,9 @@ execApp env ctxt f@(EP _ n _) args =
258263 if length args >= arity
259264 then let args' = take arity args in
260265 case getOp n args' of
261− Just res -> do r <- res
262− execApp env ctxt r (drop arity args)
263− Nothing -> return (mkEApp f args)
266+ Just (res, []) -> do r <- res
267+ execApp env ctxt r (drop arity args)
268+ _ -> return (mkEApp f args)
264269 else return (mkEApp f args)
265270 [CaseOp _ _ _ _ _ (CaseDefs _ ([], STerm tm) _ _)] -> -- nullary fun
266271 do rhs <- doExec env ctxt tm
@@ -387,8 +392,8 @@ execForeign env ctxt arity ty fn xs onfail
387392 Nothing -> fail $ "Could not call foreign function \"" ++ f ++
388393 "\" with args " ++ show (map snd argTs)
389394 Just r -> return (mkEApp r xs')
390− Nothing -> return onfail
391−
395+ _ -> return onfail
396+
392397
393398splitArg tm | (_, [_,_,l,r]) <- unApplyV tm -- pair, two implicits
394399 = Just (toFDesc l, r)
@@ -416,38 +421,47 @@ upio = sUN "unsafePerformPrimIO"
416421delay = sUN "Delay"
417422force = sUN "Force"
418423
419−-- | Look up primitive operations in the global table and transform them into ExecVal functions
420−getOp :: Name -> [ExecVal] -> Maybe (Exec ExecVal)
421−getOp fn [_, _, x] | fn == pbm = Just (return x)
422−getOp fn [_, EConstant (Str n)]
424+-- | Look up primitive operations in the global table and transform
425+-- them into ExecVal functions
426+getOp :: Name -> [ExecVal] -> Maybe (Exec ExecVal, [ExecVal])
427+getOp fn (_ : _ : x : xs) | fn == pbm = Just (return x, xs)
428+getOp fn (_ : EConstant (Str n) : xs)
423429 | fn == pws =
424− Just $ do execIO $ putStr n
425− return (EConstant (I 0))
426−getOp fn [_]
430+ Just (do execIO $ putStr n
431+ return (EConstant (I 0)), xs)
432+getOp fn (_:xs)
427433 | fn == prs =
428− Just $ do line <- execIO getLine
429− return (EConstant (Str line))
430−getOp fn [_, EP _ fn' _, EConstant (Str n)]
434+ Just (do line <- execIO getLine
435+ return (EConstant (Str line)), xs)
436+getOp fn (_ : EP _ fn' _ : EConstant (Str n) : xs)
431437 | fn == pwf && fn' == pstdout =
432− Just $ do execIO $ putStr n
433− return (EConstant (I 0))
434−getOp fn [_, EP _ fn' _]
438+ Just (do execIO $ putStr n
439+ return (EConstant (I 0)), xs)
440+getOp fn (_ : EP _ fn' _ : xs)
435441 | fn == prf && fn' == pstdin =
436− Just $ do line <- execIO getLine
437− return (EConstant (Str line))
438−getOp fn [_, EHandle h, EConstant (Str n)]
442+ Just (do line <- execIO getLine
443+ return (EConstant (Str line)), xs)
444+getOp fn (_ : EHandle h : EConstant (Str n) : xs)
439445 | fn == pwf =
440− Just $ do execIO $ hPutStr h n
441− return (EConstant (I 0))
442−getOp fn [_, EHandle h]
446+ Just (do execIO $ hPutStr h n
447+ return (EConstant (I 0)), xs)
448+getOp fn (_ : EHandle h : xs)
449+ | fn == prf =
450+ Just (do contents <- execIO $ hGetLine h
451+ return (EConstant (Str (contents ++ "\n"))), xs)
452+getOp fn (_ : arg : xs)
443453 | fn == prf =
444− Just $ do contents <- execIO $ hGetLine h
445− return (EConstant (Str (contents ++ "\n")))
446−getOp n args = getPrim n primitives >>= flip applyPrim args
447− where getPrim :: Name -> [Prim] -> Maybe ([ExecVal] -> Maybe ExecVal)
454+ Just $ (execFail (Msg "Can't use prim__readFile on a raw pointer in the executor."), xs)
455+getOp n args = do (arity, prim) <- getPrim n primitives
456+ if (length args >= arity)
457+ then do res <- applyPrim prim (take arity args)
458+ Just (res, drop arity args)
459+ else Nothing
460+ where getPrim :: Name -> [Prim] -> Maybe (Int, [ExecVal] -> Maybe ExecVal)
448461 getPrim n [] = Nothing
449− getPrim n ((Prim pn _ arity def _ _) : prims) | n == pn = Just $ execPrim def
450− | otherwise = getPrim n prims
462+ getPrim n ((Prim pn _ arity def _ _) : prims)
463+ | n == pn = Just (arity, execPrim def)
464+ | otherwise = getPrim n prims
451465
452466 execPrim :: ([Const] -> Maybe Const) -> [ExecVal] -> Maybe ExecVal
453467 execPrim f args = EConstant <$> (mapM getConst args >>= f)
@@ -486,6 +500,7 @@ execCase' env ctxt amap (Case sh n alts) | Just tm <- lookup n amap =
486500 let amap' = newBindings ++ (filter (\(x,_) -> not (elem x (map fst newBindings))) amap) in
487501 execCase' env ctxt amap' newCase
488502 Nothing -> return Nothing
503+execCase' _ _ _ cse = fail $ "The impossible happened: tried to exec " ++ show cse
489504
490505chooseAlt :: ExecVal -> [CaseAlt] -> Maybe (SC, [(Name, ExecVal)])
491506chooseAlt tm (DefaultCase sc : alts) | ok tm = Just (sc, [])
@@ -505,15 +520,6 @@ chooseAlt tm (_:alts) = chooseAlt tm alts
505520chooseAlt _ [] = Nothing
506521
507522
508−
509−
510−idrisType :: FType -> ExecVal
511−idrisType FUnit = EP Ref unitTy EErased
512−idrisType ft = EConstant (idr ft)
513− where idr (FArith ty) = AType ty
514− idr FString = StrType
515− idr FPtr = PtrType
516−
517523data Foreign = FFun String [(FDesc, ExecVal)] FDesc deriving Show
518524
519525toFType :: FDesc -> FType
@@ -574,7 +580,7 @@ call (FFun name argTypes retType) args =
574580 call' (Fun _ h) args FPtr = EPtr <$> (execIO $ callFFI h (retPtr retVoid) (prepArgs args))
575581 call' (Fun _ h) args FUnit = do _ <- execIO $ callFFI h retVoid (prepArgs args)
576582 return $ EP Ref unitCon EErased
577−
583+ call' _ _ _ = fail "the impossible happened in call' in Execute.hs"
578584
579585 prepArgs = map prepArg
580586 prepArg (EConstant (I i)) = argCInt (fromIntegral i)
src/Idris/Core/TT.hs+13−43
@@ -524,7 +524,6 @@ instance Pretty NativeTy OutputAnnotation where
524524 pretty IT64 = text "Bits64"
525525
526526data IntTy = ITFixed NativeTy | ITNative | ITBig | ITChar
527− | ITVec NativeTy Int
528527 deriving (Show, Eq, Ord, Data, Typeable)
529528
530529intTyName :: IntTy -> String
@@ -532,7 +531,6 @@ intTyName ITNative = "Int"
532531intTyName ITBig = "BigInt"
533532intTyName (ITFixed sized) = "B" ++ show (nativeTyWidth sized)
534533intTyName (ITChar) = "Char"
535−intTyName (ITVec ity count) = "B" ++ show (nativeTyWidth ity) ++ "x" ++ show count
536534
537535data ArithTy = ATInt IntTy | ATFloat -- TODO: Float vectors https://github.com/idris-lang/Idris-dev/issues/1723
538536 deriving (Show, Eq, Ord, Data, Typeable)
@@ -547,7 +545,6 @@ instance Pretty ArithTy OutputAnnotation where
547545 pretty (ATInt ITBig) = text "BigInt"
548546 pretty (ATInt ITChar) = text "Char"
549547 pretty (ATInt (ITFixed n)) = pretty n
550− pretty (ATInt (ITVec e c)) = pretty e <> text "x" <> (text . show $ c)
551548 pretty ATFloat = text "Float"
552549
553550nativeTyWidth :: NativeTy -> Int
@@ -565,11 +562,9 @@ intTyWidth ITBig = error "IRTS.Lang.intTyWidth: Big integers have variable width
565562
566563data Const = I Int | BI Integer | Fl Double | Ch Char | Str String
567564 | B8 Word8 | B16 Word16 | B32 Word32 | B64 Word64
568− | B8V (Vector Word8) | B16V (Vector Word16)
569− | B32V (Vector Word32) | B64V (Vector Word64)
570565 | AType ArithTy | StrType
571566 | WorldType | TheWorld
572− | PtrType | ManagedPtrType | BufferType | VoidType | Forgot
567+ | VoidType | Forgot
573568 deriving (Eq, Ord, Data, Typeable)
574569{-!
575570deriving instance Binary Const
@@ -579,10 +574,7 @@ deriving instance NFData Const
579574isTypeConst :: Const -> Bool
580575isTypeConst (AType _) = True
581576isTypeConst StrType = True
582−isTypeConst ManagedPtrType = True
583−isTypeConst BufferType = True
584577isTypeConst WorldType = True
585−isTypeConst PtrType = True
586578isTypeConst VoidType = True
587579isTypeConst _ = False
588580
@@ -599,9 +591,6 @@ instance Pretty Const OutputAnnotation where
599591 pretty StrType = text "String"
600592 pretty TheWorld = text "%theWorld"
601593 pretty WorldType = text "prim__World"
602− pretty BufferType = text "prim__UnsafeBuffer"
603− pretty PtrType = text "Ptr"
604− pretty ManagedPtrType = text "Ptr"
605594 pretty VoidType = text "Void"
606595 pretty Forgot = text "Forgot"
607596 pretty (B8 w) = text . show $ w
@@ -620,10 +609,6 @@ constIsType (B8 _) = False
620609constIsType (B16 _) = False
621610constIsType (B32 _) = False
622611constIsType (B64 _) = False
623−constIsType (B8V _) = False
624−constIsType (B16V _) = False
625−constIsType (B32V _) = False
626−constIsType (B64V _) = False
627612constIsType _ = True
628613
629614-- | Get the docstring for a Const
@@ -633,17 +618,10 @@ constDocs c@(AType (ATInt ITNative)) = "Fixed-precision integers of undefi
633618constDocs c@(AType (ATInt ITChar)) = "Characters in some unspecified encoding"
634619constDocs c@(AType ATFloat) = "Double-precision floating-point numbers"
635620constDocs StrType = "Strings in some unspecified encoding"
636−constDocs PtrType = "Foreign pointers"
637−constDocs ManagedPtrType = "Managed pointers"
638−constDocs BufferType = "Copy-on-write buffers"
639621constDocs c@(AType (ATInt (ITFixed IT8))) = "Eight bits (unsigned)"
640622constDocs c@(AType (ATInt (ITFixed IT16))) = "Sixteen bits (unsigned)"
641623constDocs c@(AType (ATInt (ITFixed IT32))) = "Thirty-two bits (unsigned)"
642624constDocs c@(AType (ATInt (ITFixed IT64))) = "Sixty-four bits (unsigned)"
643−constDocs c@(AType (ATInt (ITVec IT8 16))) = "Vectors of sixteen eight-bit values"
644−constDocs c@(AType (ATInt (ITVec IT16 8))) = "Vectors of eight sixteen-bit values"
645−constDocs c@(AType (ATInt (ITVec IT32 4))) = "Vectors of four thirty-two-bit values"
646−constDocs c@(AType (ATInt (ITVec IT64 2))) = "Vectors of two sixty-four-bit values"
647625constDocs (Fl f) = "A float"
648626constDocs (I i) = "A fixed-precision integer"
649627constDocs (BI i) = "An arbitrary-precision integer"
@@ -657,10 +635,6 @@ constDocs (B32 w) = "The thirty-two-bit value 0x" ++
657635 showIntAtBase 16 intToDigit w ""
658636constDocs (B64 w) = "The sixty-four-bit value 0x" ++
659637 showIntAtBase 16 intToDigit w ""
660−constDocs (B8V v) = "A vector of eight-bit values"
661−constDocs (B16V v) = "A vector of sixteen-bit values"
662−constDocs (B32V v) = "A vector of thirty-two-bit values"
663−constDocs (B64V v) = "A vector of sixty-four-bit values"
664638constDocs prim = "Undocumented"
665639
666640data Universe = NullType | UniqueType | AllTypes
@@ -782,14 +756,6 @@ deriving instance NFData UExp
782756instance Sized UExp where
783757 size _ = 1
784758
785−-- We assume that universe levels have been checked, so anything external
786−-- can just have the same universe variable and we won't get any new
787−-- cycles.
788−
789−instance Binary UExp where
790− put x = return ()
791− get = return (UVar (-1))
792−
793759instance Show UExp where
794760 show (UVar x) | x < 26 = [toEnum (x + fromEnum 'a')]
795761 | otherwise = toEnum ((x `mod` 26) + fromEnum 'a') : show (x `div` 26)
@@ -801,6 +767,16 @@ data UConstraint = ULT UExp UExp -- ^ Strictly less than
801767 | ULE UExp UExp -- ^ Less than or equal to
802768 deriving (Eq, Ord)
803769
770+data ConstraintFC = ConstraintFC { uconstraint :: UConstraint,
771+ ufc :: FC }
772+ deriving Show
773+
774+instance Eq ConstraintFC where
775+ x == y = uconstraint x == uconstraint y
776+
777+instance Ord ConstraintFC where
778+ compare x y = compare (uconstraint x) (uconstraint y)
779+
804780instance Show UConstraint where
805781 show (ULT x y) = show x ++ " < " ++ show y
806782 show (ULE x y) = show x ++ " <= " ++ show y
@@ -1191,6 +1167,8 @@ safeForgetEnv env (Bind n b sc)
11911167 Just $ RBind n' b' sc'
11921168 where safeForgetEnvB env (Let t v) = liftM2 Let (safeForgetEnv env t)
11931169 (safeForgetEnv env v)
1170+ safeForgetEnvB env (Guess t v) = liftM2 Guess (safeForgetEnv env t)
1171+ (safeForgetEnv env v)
11941172 safeForgetEnvB env b = do ty' <- safeForgetEnv env (binderTy b)
11951173 Just $ fmap (\_ -> ty') b
11961174safeForgetEnv env (App f a) = liftM2 RApp (safeForgetEnv env f) (safeForgetEnv env a)
@@ -1299,22 +1277,14 @@ instance Show Const where
12991277 show (B16 x) = show x
13001278 show (B32 x) = show x
13011279 show (B64 x) = show x
1302− show (B8V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
1303− show (B16V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
1304− show (B32V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
1305− show (B64V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
13061280 show (AType ATFloat) = "Float"
13071281 show (AType (ATInt ITBig)) = "Integer"
13081282 show (AType (ATInt ITNative)) = "Int"
13091283 show (AType (ATInt ITChar)) = "Char"
13101284 show (AType (ATInt (ITFixed it))) = itBitsName it
1311− show (AType (ATInt (ITVec it c))) = itBitsName it ++ "x" ++ show c
13121285 show TheWorld = "prim__TheWorld"
13131286 show WorldType = "prim__WorldType"
13141287 show StrType = "String"
1315− show BufferType = "prim__UnsafeBuffer"
1316− show PtrType = "Ptr"
1317− show ManagedPtrType = "ManagedPtr"
13181288 show VoidType = "Void"
13191289
13201290showEnv :: (Eq n, Show n) => EnvTT n -> TT n -> String
src/Idris/Core/Typecheck.hs+35−11
@@ -86,15 +86,38 @@ check' holes ctxt env top = chk (TType (UVar (-5))) env top where
8686 | (P nt n' ty : _) <- lookupP_all (not holes) n ctxt
8787 = return (P nt n' ty, ty)
8888 | otherwise = do lift $ tfail $ NoSuchVariable n
89+ chk u env ap@(RApp f RType) | not holes
90+ -- special case to reduce constraintss
91+ = do (fv, fty) <- chk u env f
92+ let fty' = case uniqueBinders (map fst env) (finalise fty) of
93+ ty@(Bind x (Pi i s k) t) -> ty
94+ _ -> uniqueBinders (map fst env)
95+ $ case hnf ctxt env fty of
96+ ty@(Bind x (Pi i s k) t) -> ty
97+ _ -> normalise ctxt env fty
98+ case fty' of
99+ Bind x (Pi i (TType v') k) t ->
100+ do (v, cs) <- get
101+ put (v+1, ULT (UVar v) v' : cs)
102+ let apty = simplify initContext env
103+ (Bind x (Let (TType v') (TType (UVar v))) t)
104+ return (App fv (TType (UVar v)), apty)
105+ Bind x (Pi i s k) t ->
106+ do (av, aty) <- chk u env RType
107+ convertsC ctxt env aty s
108+ let apty = simplify initContext env
109+ (Bind x (Let aty av) t)
110+ return (App fv av, apty)
111+ t -> lift $ tfail $ NonFunctionType fv fty
89112 chk u env ap@(RApp f a)
90113 = do (fv, fty) <- chk u env f
91− (av, aty) <- chk u env a
92114 let fty' = case uniqueBinders (map fst env) (finalise fty) of
93115 ty@(Bind x (Pi i s k) t) -> ty
94116 _ -> uniqueBinders (map fst env)
95117 $ case hnf ctxt env fty of
96118 ty@(Bind x (Pi i s k) t) -> ty
97119 _ -> normalise ctxt env fty
120+ (av, aty) <- chk u env a
98121 case fty' of
99122 Bind x (Pi i s k) t ->
100123 do convertsC ctxt env aty s
@@ -128,24 +151,25 @@ check' holes ctxt env top = chk (TType (UVar (-5))) env top where
128151 constType (B16 _) = Constant (AType (ATInt (ITFixed IT16)))
129152 constType (B32 _) = Constant (AType (ATInt (ITFixed IT32)))
130153 constType (B64 _) = Constant (AType (ATInt (ITFixed IT64)))
131− constType (B8V a) = Constant (AType (ATInt (ITVec IT8 (V.length a))))
132− constType (B16V a) = Constant (AType (ATInt (ITVec IT16 (V.length a))))
133− constType (B32V a) = Constant (AType (ATInt (ITVec IT32 (V.length a))))
134− constType (B64V a) = Constant (AType (ATInt (ITVec IT64 (V.length a))))
135154 constType TheWorld = Constant WorldType
136155 constType Forgot = Erased
137156 constType _ = TType (UVal 0)
138− chk u env (RForce t) = do (_, ty) <- chk u env t
139− return (Erased, ty)
157+ chk u env (RForce t)
158+ = do (_, ty) <- chk u env t
159+ return (Erased, ty)
140160 chk u env (RBind n (Pi i s k) t)
141161 = do (sv, st) <- chk u env s
142− (kv, kt) <- chk u env k
143− (tv, tt) <- chk st ((n, Pi i sv kv) : env) t
144162 (v, cs) <- get
163+ (kv, kt) <- chk u env k -- no need to validate these constraints, they are independent
164+ put (v+1, cs)
165+ let maxu = UVar v
166+ (tv, tt) <- chk st ((n, Pi i sv kv) : env) t
145167 case (normalise ctxt env st, normalise ctxt env tt) of
146168 (TType su, TType tu) -> do
147− when (not holes) $ put (v+1, ULE su (UVar v):ULE tu (UVar v):cs)
148− let k' = st `smaller` kv `smaller` TType (UVar v) `smaller` u
169+ when (not holes) $ do (v, cs) <- get
170+ put (v, ULE su maxu :
171+ ULE tu maxu : cs)
172+ let k' = TType (UVar v) `smaller` st `smaller` kv `smaller` u
149173 return (Bind n (Pi i (uniqueBinders (map fst env) sv) k')
150174 (pToV n tv), k')
151175 (un, un') ->
src/Idris/DeepSeq.hs+2−2
@@ -132,9 +132,9 @@ instance (NFData t) => NFData (PDecl' t) where
132132 = rnf x1 `seq`
133133 rnf x2 `seq`
134134 rnf x3 `seq` rnf x4 `seq` rnf x5 `seq` rnf x6 `seq` rnf x7 `seq` ()
135− rnf (PPostulate x1 x2 x3 x4 x5 x6)
135+ rnf (PPostulate x1 x2 x3 x4 x5 x6 x7)
136136 = rnf x1 `seq`
137− rnf x2 `seq` rnf x3 `seq` rnf x4 `seq` rnf x5 `seq` rnf x6 `seq` ()
137+ rnf x2 `seq` rnf x3 `seq` rnf x4 `seq` rnf x5 `seq` rnf x6 `seq` rnf x7 `seq` ()
138138 rnf (PClauses x1 x2 x3 x4)
139139 = rnf x1 `seq` rnf x2 `seq` rnf x3 `seq` rnf x4 `seq` ()
140140 rnf (PCAF x1 x2 x3) = rnf x1 `seq` rnf x2 `seq` rnf x3 `seq` ()
src/Idris/Delaborate.hs+1−1
@@ -1,6 +1,6 @@
11{-# LANGUAGE PatternGuards #-}
22{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
3−module Idris.Delaborate (bugaddr, delab, delab', delabMV, delabTy, delabTy', fancifyAnnots, pprintDelab, pprintDelabTy, pprintErr) where
3+module Idris.Delaborate (annName, bugaddr, delab, delab', delabMV, delabTy, delabTy', fancifyAnnots, pprintDelab, pprintDelabTy, pprintErr) where
44
55-- Convert core TT back into high level syntax, primarily for display
66-- purposes.
src/Idris/Docs.hs+55−19
@@ -1,4 +1,5 @@
1−{-# LANGUAGE DeriveFunctor, PatternGuards #-}
1+{-# LANGUAGE DeriveFunctor, PatternGuards, MultiWayIf #-}
2+{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
23module Idris.Docs (pprintDocs, getDocs, pprintConstDocs, FunDoc, FunDoc'(..), Docs, Docs'(..)) where
34
45import Idris.AbsSyntax
@@ -10,6 +11,8 @@ import Idris.Docstrings (Docstring, emptyDocstring, noDocs, nullDocstring, rende
1011
1112import Util.Pretty
1213
14+import Control.Arrow (first)
15+
1316import Data.Maybe
1417import Data.List
1518import qualified Data.Text as T
@@ -32,9 +35,10 @@ data Docs' d = FunDoc (FunDoc' d)
3235 | ClassDoc Name d -- class docs
3336 [FunDoc' d] -- method docs
3437 [(Name, Maybe d)] -- parameters and their docstrings
35− [(PTerm, (d, [(Name, d)]))] -- instances
38+ [(Maybe Name, PTerm, (d, [(Name, d)]))] -- instances: name for named instances, the constraint term, the docs
3639 [PTerm] -- subclasses
3740 [PTerm] -- superclasses
41+ | NamedInstanceDoc Name (FunDoc' d) -- name is class
3842 | ModDoc [String] -- Module name
3943 d
4044 deriving Functor
@@ -102,7 +106,11 @@ pprintDocs ist (ClassDoc n doc meths params instances subclasses superclasses)
102106 <$>
103107 nest 4 (text "Instances:" <$>
104108 vsep (if null instances then [text "<no instances>"]
105− else map pprintInstance instances))
109+ else map pprintInstance normalInstances))
110+ <>
111+ (if null namedInstances then empty
112+ else line <$> nest 4 (text "Named instances:" <$>
113+ vsep (map pprintInstance namedInstances)))
106114 <>
107115 (if null subclasses then empty
108116 else line <$> nest 4 (text "Subclasses:" <$>
@@ -113,14 +121,17 @@ pprintDocs ist (ClassDoc n doc meths params instances subclasses superclasses)
113121 vsep (map dumpInstance superclasses)))
114122 where
115123 params' = zip pNames (repeat False)
124+
125+ (normalInstances, namedInstances) = partition (\(n, _, _) -> not $ isJust n)
126+ instances
116127
117128 pNames = map fst params
118129
119130 ppo = ppOptionIst ist
120131 infixes = idris_infixes ist
121132
122− pprintInstance (term, (doc, argDocs)) =
123− nest 4 (dumpInstance term <>
133+ pprintInstance (mname, term, (doc, argDocs)) =
134+ nest 4 (iname mname <> dumpInstance term <>
124135 (if nullDocstring doc
125136 then empty
126137 else line <>
@@ -133,6 +144,10 @@ pprintDocs ist (ClassDoc n doc meths params instances subclasses superclasses)
133144 then empty
134145 else line <> vsep (map (prettyInstanceParam (map fst argDocs)) argDocs))
135146
147+
148+ iname Nothing = empty
149+ iname (Just n) = annName n <+> colon <> space
150+
136151 prettyInstanceParam params (name, doc) =
137152 if nullDocstring doc
138153 then empty
@@ -170,6 +185,9 @@ pprintDocs ist (ClassDoc n doc meths params instances subclasses superclasses)
170185 then vsep (map (\(nm,md) -> prettyName True False params' nm <+> maybe empty (showDoc ist) md) params)
171186 else hsep (punctuate comma (map (prettyName True False params' . fst) params))
172187
188+pprintDocs ist (NamedInstanceDoc _cls doc)
189+ = nest 4 (text "Named instance:" <$> pprintFD ist doc)
190+
173191pprintDocs ist (ModDoc mod docs)
174192 = nest 4 $ text "Module" <+> text (concat (intersperse "." mod)) <> colon <$>
175193 renderDocstring (renderDocTerm (pprintDelab ist) (normaliseAll (tt_ctxt ist) [])) docs
@@ -190,13 +208,23 @@ getDocs n@(NS n' ns) w | n' == modDocName
190208 " do not exist! This shouldn't have happened and is a bug."
191209getDocs n w
192210 = do i <- getIState
193− docs <- case lookupCtxt n (idris_classes i) of
194− [ci] -> docClass n ci
195− _ -> case lookupCtxt n (idris_datatypes i) of
196− [ti] -> docData n ti
197− _ -> do fd <- docFun n
198− return (FunDoc fd)
211+ docs <- if | Just ci <- lookupCtxtExact n (idris_classes i)
212+ -> docClass n ci
213+ | Just ti <- lookupCtxtExact n (idris_datatypes i)
214+ -> docData n ti
215+ | Just class_ <- classNameForInst i n
216+ -> do fd <- docFun n
217+ return $ NamedInstanceDoc class_ fd
218+ | otherwise
219+ -> do fd <- docFun n
220+ return (FunDoc fd)
199221 return $ fmap (howMuch w) docs
222+ where classNameForInst :: IState -> Name -> Maybe Name
223+ classNameForInst ist n =
224+ listToMaybe [ cn
225+ | (cn, ci) <- toAlist (idris_classes ist)
226+ , n `elem` class_instances ci
227+ ]
200228
201229docData :: Name -> TypeInfo -> Idris Docs
202230docData n ti
@@ -209,19 +237,26 @@ docClass n ci
209237 = do i <- getIState
210238 let docStrings = listToMaybe $ lookupCtxt n $ idris_docstrings i
211239 docstr = maybe emptyDocstring fst docStrings
212− params = map (\pn -> (pn, docStrings >>= (lookup pn . snd))) (class_params ci)
213− instanceDocs = map (fromMaybe (emptyDocstring, []) .
214− listToMaybe .
215− flip lookupCtxt (idris_docstrings i))
216− (class_instances ci)
217− instances = zip (map (delabTy i) (class_instances ci)) instanceDocs
218− (subclasses, instances') = partition (isSubclass . fst) instances
240+ params = map (\pn -> (pn, docStrings >>= (lookup pn . snd)))
241+ (class_params ci)
242+ docsForInstance inst = fromMaybe (emptyDocstring, []) .
243+ flip lookupCtxtExact (idris_docstrings i) $
244+ inst
245+ instances = map (\inst -> (namedInst inst,
246+ delabTy i inst,
247+ docsForInstance inst))
248+ (nub (class_instances ci))
249+ (subclasses, instances') = partition (isSubclass . (\(_,tm,_) -> tm)) instances
219250 superclasses = catMaybes $ map getDInst (class_default_superclasses ci)
220251 mdocs <- mapM (docFun . fst) (class_methods ci)
221252 return $ ClassDoc
222253 n docstr mdocs params
223− instances' (map fst subclasses) superclasses
254+ instances' (map (\(_,tm,_) -> tm) subclasses) superclasses
224255 where
256+ namedInst (NS n ns) = fmap (flip NS ns) (namedInst n)
257+ namedInst n@(UN _) = Just n
258+ namedInst _ = Nothing
259+
225260 getDInst (PInstance _ _ _ _ _ _ _ t _ _) = Just t
226261 getDInst _ = Nothing
227262
@@ -250,6 +285,7 @@ docFun n
250285 where funName :: Name -> String
251286 funName (UN n) = str n
252287 funName (NS n _) = funName n
288+ funName n = show n
253289
254290getPArgNames :: PTerm -> [(Name, Docstring DocTerm)] -> [(Name, PTerm, Plicity, Maybe (Docstring DocTerm))]
255291getPArgNames (PPi plicity name ty body) ds =
src/Idris/Elab/Class.hs+4−3
@@ -69,7 +69,7 @@ elabClass info syn_in doc fc constraints tn ps pDocs fds ds
6969 let idecls = filter instdecl ds -- default superclass instance declarations
7070 mapM_ checkDefaultSuperclassInstance idecls
7171 let mnames = map getMName mdecls
72− logLvl 2 $ "Building methods " ++ show mnames
72+ logLvl 1 $ "Building methods " ++ show mnames
7373 ims <- mapM (tdecl mnames) mdecls
7474 defs <- mapM (defdecl (map (\ (x,y,z) -> z) ims) constraint)
7575 (filter clause ds)
@@ -94,7 +94,8 @@ elabClass info syn_in doc fc constraints tn ps pDocs fds ds
9494 mapM_ (rec_elabDecl info EAll info) (concat cfns)
9595
9696 -- for each method, build a top level function
97− fns <- mapM (tfun cn constraint syn (map fst imethods)) imethods
97+ fns <- mapM (tfun cn constraint (syn { imp_methods = mnames })
98+ (map fst imethods)) imethods
9899 logLvl 5 $ "Functions " ++ show fns
99100 -- Elaborate the the top level methods
100101 mapM_ (rec_elabDecl info EAll info) (concat fns)
@@ -199,7 +200,7 @@ elabClass info syn_in doc fc constraints tn ps pDocs fds ds
199200 let anames = map (\x -> sMN x "arg") [0..]
200201 let lhs = PApp fc (PRef fc m) (pconst capp : lhsArgs margs anames)
201202 let rhs = PApp fc (getMeth mnames all m) (rhsArgs margs anames)
202− iLOG (showTmImpls ty)
203+ iLOG (showTmImpls ty')
203204 iLOG (show (m, ty', capp, margs))
204205 iLOG (showTmImpls lhs ++ " = " ++ showTmImpls rhs)
205206 return [PTy doc [] syn fc o m ty',
src/Idris/Elab/Data.hs+13−4
@@ -64,7 +64,7 @@ elabData info syn doc argDocs fc opts (PDatadecl n t_in dcons)
6464 = do let codata = Codata `elem` opts
6565 iLOG (show fc)
6666 undef <- isUndefined fc n
67− (cty, _, t, inacc) <- buildType info syn fc [] n t_in
67+ (cty, ckind, t, inacc) <- buildType info syn fc [] n t_in
6868 -- if n is defined already, make sure it is just a type declaration
6969 -- with the same type we've just elaborated, and no constructors
7070 -- yet
@@ -76,7 +76,7 @@ elabData info syn doc argDocs fc opts (PDatadecl n t_in dcons)
7676 let unique = case getRetTy cty of
7777 UType UniqueType -> True
7878 _ -> False
79− cons <- mapM (elabCon cnameinfo syn n codata (getRetTy cty)) dcons
79+ cons <- mapM (elabCon cnameinfo syn n codata (getRetTy cty) ckind) dcons
8080 ttag <- getName
8181 i <- getIState
8282 let as = map (const (Left (Msg ""))) (getArgTys cty)
@@ -210,16 +210,18 @@ elabData info syn doc argDocs fc opts (PDatadecl n t_in dcons)
210210 }
211211
212212elabCon :: ElabInfo -> SyntaxInfo -> Name -> Bool ->
213− Type -> -- for kind checking
213+ Type -> -- for unique kind checking
214+ Type -> -- data type's kind
214215 (Docstring (Either Err PTerm), [(Name, Docstring (Either Err PTerm))], Name, PTerm, FC, [Name]) ->
215216 Idris (Name, Type)
216−elabCon info syn tn codata expkind (doc, argDocs, n, t_in, fc, forcenames)
217+elabCon info syn tn codata expkind dkind (doc, argDocs, n, t_in, fc, forcenames)
217218 = do checkUndefined fc n
218219 logLvl 2 $ show fc ++ ":Constructor " ++ show n ++ " : " ++ show t_in
219220 (cty, ckind, t, inacc) <- buildType info syn fc [Constructor] n (if codata then mkLazy t_in else t_in)
220221 ctxt <- getContext
221222 let cty' = normalise ctxt [] cty
222223 checkUniqueKind ckind expkind
224+ addDataConstraint ckind dkind
223225
224226 -- Check that the constructor type is, in fact, a part of the family being defined
225227 tyIs n cty'
@@ -280,6 +282,13 @@ elabCon info syn tn codata expkind (doc, argDocs, n, t_in, fc, forcenames)
280282 checkUniqueKind (UType AllTypes) _ = return ()
281283 checkUniqueKind _ _ = return ()
282284
285+ -- Constructor's kind must be <= expected kind
286+ addDataConstraint (TType con) (TType exp)
287+ = do ctxt <- getContext
288+ let v = next_tvar ctxt
289+ addConstraints fc (v, [ULT con exp])
290+ addDataConstraint _ _ = return ()
291+
283292type EliminatorState = StateT (Map.Map String Int) Idris
284293
285294-- -- Issue #1616 in the issue tracker.
src/Idris/Elab/Instance.hs+25−3
@@ -88,6 +88,7 @@ elabInstance info syn doc argDocs what fc cs n ps t expn ds = do
8888 -- where block
8989 wparams <- mapM (\p -> case p of
9090 PApp _ _ args -> getWParams (map getTm args)
91+ a@(PRef fc f) -> getWParams [a]
9192 _ -> return []) ps
9293 let pnames = map pname (concat (nub wparams))
9394 let superclassInstances = map (substInstance ips pnames) (class_default_superclasses ci)
@@ -103,8 +104,11 @@ elabInstance info syn doc argDocs what fc cs n ps t expn ds = do
103104 op, coninsert cs t', t'))
104105 (class_methods ci)
105106 logLvl 3 (show (mtys, ips))
106− let ds' = insertDefaults i iname (class_defaults ci) ns ds
107− iLOG ("Defaults inserted: " ++ show ds' ++ "\n" ++ show ci)
107+ logLvl 5 ("Before defaults: " ++ show ds ++ "\n" ++ show (map fst (class_methods ci)))
108+ let ds_defs = insertDefaults i iname (class_defaults ci) ns ds
109+ logLvl 3 ("After defaults: " ++ show ds_defs ++ "\n")
110+ let ds' = reorderDefs (map fst (class_methods ci)) $ ds_defs
111+ iLOG ("Reordered: " ++ show ds' ++ "\n")
108112 mapM_ (warnMissing ds' ns iname) (map fst (class_methods ci))
109113 mapM_ (checkInClass (map fst (class_methods ci))) (concatMap defined ds')
110114 let wbTys = map mkTyDecl mtys
@@ -239,7 +243,9 @@ elabInstance info syn doc argDocs what fc cs n ps t expn ds = do
239243 decorate ns iname (UN n) = NS (SN (MethodN (UN n))) ns
240244 decorate ns iname (NS (UN n) s) = NS (SN (MethodN (UN n))) ns
241245
242− mkTyDecl (n, op, t, _) = PTy emptyDocstring [] syn fc op n t
246+ mkTyDecl (n, op, t, _)
247+ = PTy emptyDocstring [] syn fc op n
248+ (mkUniqueNames [] t)
243249
244250 conbind :: [(Name, PTerm)] -> PTerm -> PTerm
245251 conbind ((c,ty) : ns) x = PPi constraint c ty (conbind ns x)
@@ -249,6 +255,22 @@ elabInstance info syn doc argDocs what fc cs n ps t expn ds = do
249255 coninsert cs (PPi p@(Imp _ _ _ _) n t sc) = PPi p n t (coninsert cs sc)
250256 coninsert cs sc = conbind cs sc
251257
258+ -- Reorder declarations to be in the same order as defined in the
259+ -- class declaration (important so that we insert default definitions
260+ -- in the right place, and so that dependencies between methods are
261+ -- respected)
262+ reorderDefs :: [Name] -> [PDecl] -> [PDecl]
263+ reorderDefs ns [] = []
264+ reorderDefs [] ds = ds
265+ reorderDefs (n : ns) ds = case pick n [] ds of
266+ Just (def, ds') -> def : reorderDefs ns ds'
267+ Nothing -> reorderDefs ns ds
268+
269+ pick n acc [] = Nothing
270+ pick n acc (def@(PClauses _ _ cn cs) : ds)
271+ | nsroot n == nsroot cn = Just (def, acc ++ ds)
272+ pick n acc (d : ds) = pick n (acc ++ [d]) ds
273+
252274 insertDefaults :: IState -> Name ->
253275 [(Name, (Name, PDecl))] -> [T.Text] ->
254276 [PDecl] -> [PDecl]
src/Idris/Elab/Provider.hs+1−1
@@ -112,7 +112,7 @@ elabProvider doc info syn fc what n
112112 -- error messages with less normalisation
113113 providerOf :: Type -> Type
114114 providerOf ty = App (P Ref (sUN "IO") Erased) $
115− App (P Ref (sNS (sUN "Provider") ["Providers"]) Erased)
115+ App (P Ref (sNS (sUN "Provider") ["Providers", "Prelude"]) Erased)
116116 ty
117117
118118 isProviderOf :: Context -> TT Name -> TT Name -> Bool
src/Idris/Elab/Type.hs+15−1
@@ -1,5 +1,6 @@
11{-# LANGUAGE PatternGuards #-}
2−module Idris.Elab.Type (buildType, elabType, elabType', elabPostulate) where
2+module Idris.Elab.Type (buildType, elabType, elabType',
3+ elabPostulate, elabExtern) where
34
45import Idris.AbsSyntax
56import Idris.ASTUtils
@@ -229,5 +230,18 @@ elabPostulate info syn doc fc opts n ty = do
229230 -- remove it from the deferred definitions list
230231 solveDeferred n
231232
233+elabExtern :: ElabInfo -> SyntaxInfo -> Docstring (Either Err PTerm) ->
234+ FC -> FnOpts -> Name -> PTerm -> Idris ()
235+elabExtern info syn doc fc opts n ty = do
236+ cty <- elabType info syn doc [] fc opts n ty
237+ ist <- getIState
238+ let arity = length (getArgTys (normalise (tt_ctxt ist) [] cty))
239+
240+ putIState . (\ist -> ist{ idris_externs = S.insert (n, arity) (idris_externs ist) }) =<< getIState
241+ addIBC (IBCExtern (n, arity))
242+
243+ -- remove it from the deferred definitions list
244+ solveDeferred n
245+
232246
233247
src/Idris/ElabDecls.hs+4−2
@@ -160,10 +160,12 @@ elabDecl' what info (PTy doc argdocs s f o n ty)
160160 = do iLOG $ "Elaborating type decl " ++ show n ++ show o
161161 elabType info s doc argdocs f o n ty
162162 return ()
163−elabDecl' what info (PPostulate doc s f o n ty)
163+elabDecl' what info (PPostulate b doc s f o n ty)
164164 | what /= EDefns
165165 = do iLOG $ "Elaborating postulate " ++ show n ++ show o
166− elabPostulate info s doc f o n ty
166+ if b
167+ then elabExtern info s doc f o n ty
168+ else elabPostulate info s doc f o n ty
167169elabDecl' what info (PData doc argDocs s f co d)
168170 | what /= ETypes
169171 = do iLOG $ "Elaborating " ++ show (d_name d)
src/Idris/ElabTerm.hs+14−26
@@ -29,8 +29,6 @@ import qualified Data.Map as M
2929import Data.Maybe (mapMaybe, fromMaybe)
3030import qualified Data.Set as S
3131import qualified Data.Text as T
32−import Data.Vector.Unboxed (Vector)
33−import qualified Data.Vector.Unboxed as V
3432
3533import Debug.Trace
3634
@@ -119,9 +117,9 @@ build ist info emode opts fn tm
119117 if inf then return ()
120118 else lift (Error e)
121119
122− when tydecl (do update_term orderPats
123− mkPat)
124−-- update_term liftPats)
120+ when tydecl (do mkPat
121+ update_term liftPats
122+ update_term orderPats)
125123 EState is _ impls <- getAux
126124 tt <- get_term
127125 let (tm, ds) = runState (collectDeferred (Just fn) tt) []
@@ -319,7 +317,6 @@ elab ist info emode opts fn tm
319317 constType :: Const -> Bool
320318 constType (AType _) = True
321319 constType StrType = True
322− constType PtrType = True
323320 constType VoidType = True
324321 constType _ = False
325322
@@ -475,7 +472,7 @@ elab ist info emode opts fn tm
475472 _ -> True
476473 -- this is to stop us resolve type classes recursively
477474 -- trace (show (n, guarded)) $
478− if (tcname n && ina) then erun fc $ do patvar n; -- update_term liftPats
475+ if (tcname n && ina) then erun fc $ do patvar n; update_term liftPats
479476 else if (defined && not guarded)
480477 then do apply (Var n) []; solve
481478 else try (do apply (Var n) []; solve)
@@ -805,10 +802,10 @@ elab ist info emode opts fn tm
805802 Just b ->
806803 case unApply (binderTy b) of
807804 (P _ c _, args) ->
808− case lookupCtxt c (idris_classes ist) of
809− [] -> return ()
810− _ -> -- type class, set as injective
811− do mapM_ setinjArg args
805+ case lookupCtxtExact c (idris_classes ist) of
806+ Nothing -> return ()
807+ Just ci -> -- type class, set as injective
808+ do mapM_ setinjArg (getDets 0 (class_determiners ci) args)
812809 -- maybe we can solve more things now...
813810 ulog <- getUnifyLog
814811 probs <- get_probs
@@ -821,6 +818,10 @@ elab ist info emode opts fn tm
821818 setinjArg (P _ n _) = setinj n
822819 setinjArg _ = return ()
823820
821+ getDets i ds [] = []
822+ getDets i ds (a : as) | i `elem` ds = a : getDets (i + 1) ds as
823+ | otherwise = getDets (i + 1) ds as
824+
824825 tacTm (PTactics _) = True
825826 tacTm (PProof _) = True
826827 tacTm _ = False
@@ -1730,7 +1731,8 @@ runTac autoSolve ist perhapsFC fn tac
17301731 bname _ = Nothing
17311732 runT (Intro xs) = mapM_ (\x -> do attack; intro (Just x)) xs
17321733 runT Intros = do g <- goal
1733− attack; intro (bname g)
1734+ attack;
1735+ intro (bname g)
17341736 try' (runT Intros)
17351737 (return ()) True
17361738 where
@@ -2165,7 +2167,6 @@ reifyTTBinderApp _ f args = fail ("Unknown reflection binder: " ++ show (f, args
21652167
21662168reifyTTConst :: Term -> ElabD Const
21672169reifyTTConst (P _ n _) | n == reflm "StrType" = return $ StrType
2168−reifyTTConst (P _ n _) | n == reflm "PtrType" = return $ PtrType
21692170reifyTTConst (P _ n _) | n == reflm "VoidType" = return $ VoidType
21702171reifyTTConst (P _ n _) | n == reflm "Forgot" = return $ Forgot
21712172reifyTTConst t@(App _ _)
@@ -2212,8 +2213,6 @@ reifyIntTy (App (P _ n _) nt) | n == reflm "ITFixed" = fmap ITFixed (reifyNative
22122213reifyIntTy (P _ n _) | n == reflm "ITNative" = return ITNative
22132214reifyIntTy (P _ n _) | n == reflm "ITBig" = return ITBig
22142215reifyIntTy (P _ n _) | n == reflm "ITChar" = return ITChar
2215−reifyIntTy (App (App (P _ n _) nt) (Constant (I i))) | n == reflm "ITVec" = fmap (flip ITVec i)
2216− (reifyNativeTy nt)
22172216reifyIntTy tm = fail $ "The term " ++ show tm ++ " is not a reflected IntTy"
22182217
22192218reifyTTUExp :: Term -> ElabD UExp
@@ -2581,10 +2580,6 @@ reflectConstant c@(B8 _) = reflCall "B8" [RConstant c]
25812580reflectConstant c@(B16 _) = reflCall "B16" [RConstant c]
25822581reflectConstant c@(B32 _) = reflCall "B32" [RConstant c]
25832582reflectConstant c@(B64 _) = reflCall "B64" [RConstant c]
2584−reflectConstant (B8V ws) = reflCall "B8V" [mkList (Var (sUN "Bits8")) . map (RConstant . B8) . V.toList $ ws]
2585−reflectConstant (B16V ws) = reflCall "B8V" [mkList (Var (sUN "Bits16")) . map (RConstant . B16) . V.toList $ ws]
2586−reflectConstant (B32V ws) = reflCall "B8V" [mkList (Var (sUN "Bits32")) . map (RConstant . B32) . V.toList $ ws]
2587−reflectConstant (B64V ws) = reflCall "B8V" [mkList (Var (sUN "Bits64")) . map (RConstant . B64) . V.toList $ ws]
25882583reflectConstant (AType (ATInt ITNative)) = reflCall "AType" [reflCall "ATInt" [Var (reflm "ITNative")]]
25892584reflectConstant (AType (ATInt ITBig)) = reflCall "AType" [reflCall "ATInt" [Var (reflm "ITBig")]]
25902585reflectConstant (AType ATFloat) = reflCall "AType" [Var (reflm "ATFloat")]
@@ -2594,13 +2589,6 @@ reflectConstant (AType (ATInt (ITFixed IT8))) = reflCall "AType" [reflCall "ATI
25942589reflectConstant (AType (ATInt (ITFixed IT16))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITFixed" [Var (reflm "IT16")]]]
25952590reflectConstant (AType (ATInt (ITFixed IT32))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITFixed" [Var (reflm "IT32")]]]
25962591reflectConstant (AType (ATInt (ITFixed IT64))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITFixed" [Var (reflm "IT64")]]]
2597−reflectConstant (AType (ATInt (ITVec IT8 c))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITVec" [Var (reflm "IT8"), RConstant (I c)]]]
2598−reflectConstant (AType (ATInt (ITVec IT16 c))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITVec" [Var (reflm "IT16"), RConstant (I c)]]]
2599−reflectConstant (AType (ATInt (ITVec IT32 c))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITVec" [Var (reflm "IT32"), RConstant (I c)]]]
2600−reflectConstant (AType (ATInt (ITVec IT64 c))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITVec" [Var (reflm "IT64"), RConstant (I c)]]]
2601−reflectConstant PtrType = Var (reflm "PtrType")
2602−reflectConstant ManagedPtrType = Var (reflm "ManagedPtrType")
2603−reflectConstant BufferType = Var (reflm "BufferType")
26042592reflectConstant VoidType = Var (reflm "VoidType")
26052593reflectConstant Forgot = Var (reflm "Forgot")
26062594reflectConstant WorldType = Var (reflm "WorldType")
src/Idris/Erasure.hs+9−4
@@ -77,9 +77,10 @@ performUsageAnalysis roots = do
7777 cg <- idris_callgraph <$> getIState
7878 opt <- idris_optimisation <$> getIState
7979 used <- idris_erasureUsed <$> getIState
80+ externs <- idris_externs <$> getIState
8081
8182 -- Build the dependency graph.
82− let depMap = buildDepMap ci used ctx main
83+ let depMap = buildDepMap ci used (S.toList externs) ctx main
8384
8485 -- Search for reachable nodes in the graph.
8586 let (residDeps, (reachableNames, minUse)) = minimalUsage depMap
@@ -174,9 +175,10 @@ forwardChain deps
174175
175176-- Build the dependency graph,
176177-- starting the depth-first search from a list of Names.
177−buildDepMap :: Ctxt ClassInfo -> [(Name, Int)] -> Context -> [Name] -> Deps
178−buildDepMap ci used ctx startNames = addPostulates used $
179− dfs S.empty M.empty startNames
178+buildDepMap :: Ctxt ClassInfo -> [(Name, Int)] -> [(Name, Int)] ->
179+ Context -> [Name] -> Deps
180+buildDepMap ci used externs ctx startNames
181+ = addPostulates used $ dfs S.empty M.empty startNames
180182 where
181183 -- mark the result of Main.main as used with the empty assumption
182184 addPostulates :: [(Name, Int)] -> Deps -> Deps
@@ -226,6 +228,9 @@ buildDepMap ci used ctx startNames = addPostulates used $
226228 -- in general, all other primitives use all their arguments
227229 , [(n, Arg i) | (n,arity) <- usedPrims, i <- [0..arity-1]]
228230
231+ -- %externs are assumed to use all their arguments
232+ , [(n, Arg i) | (n,arity) <- externs, i <- [0..arity-1]]
233+
229234 -- mkForeign* functions are special-cased below
230235 ]
231236 ]
src/Idris/IBC.hs+18−6
@@ -37,7 +37,7 @@ import Codec.Compression.Zlib (compress)
3737import Util.Zlib (decompressEither)
3838
3939ibcVersion :: Word8
40−ibcVersion = 100
40+ibcVersion = 103
4141
4242data IBCFile = IBCFile { ver :: Word8,
4343 sourcefile :: FilePath,
@@ -79,6 +79,7 @@ data IBCFile = IBCFile { ver :: Word8,
7979 ibc_metavars :: ![(Name, (Maybe Name, Int, Bool))],
8080 ibc_patdefs :: ![(Name, ([([Name], Term, Term)], [PTerm]))],
8181 ibc_postulates :: ![Name],
82+ ibc_externs :: ![(Name, Int)],
8283 ibc_parsedSpan :: !(Maybe FC),
8384 ibc_usage :: ![(Name, Int)],
8485 ibc_exports :: ![Name]
@@ -89,7 +90,7 @@ deriving instance Binary IBCFile
8990!-}
9091
9192initIBC :: IBCFile
92−initIBC = IBCFile ibcVersion "" [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] Nothing [] []
93+initIBC = IBCFile ibcVersion "" [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] Nothing [] []
9394
9495loadIBC :: Bool -- ^ True = reexport, False = make everything private
9596 -> FilePath -> Idris ()
@@ -228,6 +229,7 @@ ibc i (IBCMetavar n) f =
228229 Nothing -> return f
229230 Just t -> return f { ibc_metavars = (n, t) : ibc_metavars f }
230231ibc i (IBCPostulate n) f = return f { ibc_postulates = n : ibc_postulates f }
232+ibc i (IBCExtern n) f = return f { ibc_externs = n : ibc_externs f }
231233ibc i (IBCTotCheckErr fc err) f = return f { ibc_totcheckfail = (fc, err) : ibc_totcheckfail f }
232234ibc i (IBCParsedRegion fc) f = return f { ibc_parsedSpan = Just fc }
233235ibc i (IBCModDocs n) f = case lookupCtxtExact n (idris_moduledocs i) of
@@ -290,6 +292,7 @@ process reexp i fn
290292 pFunctionErrorHandlers $ force (ibc_function_errorhandlers i)
291293 pMetavars $ force (ibc_metavars i)
292294 pPostulates $ force (ibc_postulates i)
295+ pExterns $ force (ibc_externs i)
293296 pParsedSpan $ force (ibc_parsedSpan i)
294297 pUsage $ force (ibc_usage i)
295298 pExports $ force (ibc_exports i)
@@ -306,6 +309,11 @@ pPostulates ns = do
306309 i <- getIState
307310 putIState i{ idris_postulates = idris_postulates i `S.union` S.fromList ns }
308311
312+pExterns :: [(Name, Int)] -> Idris ()
313+pExterns ns = do
314+ i <- getIState
315+ putIState i{ idris_externs = idris_externs i `S.union` S.fromList ns }
316+
309317pParsedSpan :: Maybe FC -> Idris ()
310318pParsedSpan fc = do ist <- getIState
311319 putIState ist { idris_parsedSpan = fc }
@@ -934,7 +942,7 @@ instance Binary MetaInformation where
934942 _ -> error "Corrupted binary data for MetaInformation"
935943
936944instance Binary IBCFile where
937− put x@(IBCFile x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 x21 x22 x23 x24 x25 x26 x27 x28 x29 x30 x31 x32 x33 x34 x35 x36 x37 x38 x39 x40 x41 x42 x43)
945+ put x@(IBCFile x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 x21 x22 x23 x24 x25 x26 x27 x28 x29 x30 x31 x32 x33 x34 x35 x36 x37 x38 x39 x40 x41 x42 x43 x44)
938946 = {-# SCC "putIBCFile" #-}
939947 do put x1
940948 put x2
@@ -979,6 +987,7 @@ instance Binary IBCFile where
979987 put x41
980988 put x42
981989 put x43
990+ put x44
982991
983992 get
984993 = do x1 <- get
@@ -1025,7 +1034,8 @@ instance Binary IBCFile where
10251034 x41 <- get
10261035 x42 <- get
10271036 x43 <- get
1028− return (IBCFile x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 x21 x22 x23 x24 x25 x26 x27 x28 x29 x30 x31 x32 x33 x34 x35 x36 x37 x38 x39 x40 x41 x42 x43)
1037+ x44 <- get
1038+ return (IBCFile x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 x21 x22 x23 x24 x25 x26 x27 x28 x29 x30 x31 x32 x33 x34 x35 x36 x37 x38 x39 x40 x41 x42 x43 x44)
10291039 else return (initIBC { ver = x1 })
10301040
10311041instance Binary DataOpt where
@@ -1273,7 +1283,7 @@ instance (Binary t) => Binary (PDecl' t) where
12731283 PMutual x1 x2 -> do putWord8 11
12741284 put x1
12751285 put x2
1276− PPostulate x1 x2 x3 x4 x5 x6
1286+ PPostulate x1 x2 x3 x4 x5 x6 x7
12771287 -> do putWord8 12
12781288 put x1
12791289 put x2
@@ -1281,6 +1291,7 @@ instance (Binary t) => Binary (PDecl' t) where
12811291 put x4
12821292 put x5
12831293 put x6
1294+ put x7
12841295 PSyntax x1 x2 -> do putWord8 13
12851296 put x1
12861297 put x2
@@ -1380,7 +1391,8 @@ instance (Binary t) => Binary (PDecl' t) where
13801391 x4 <- get
13811392 x5 <- get
13821393 x6 <- get
1383− return (PPostulate x1 x2 x3 x4 x5 x6)
1394+ x7 <- get
1395+ return (PPostulate x1 x2 x3 x4 x5 x6 x7)
13841396 13 -> do x1 <- get
13851397 x2 <- get
13861398 return (PSyntax x1 x2)
src/Idris/IdeMode.hs−4
@@ -113,10 +113,6 @@ constTy (B8 _) = "Bits8"
113113constTy (B16 _) = "Bits16"
114114constTy (B32 _) = "Bits32"
115115constTy (B64 _) = "Bits64"
116−constTy (B8V _) = "Bits8x16"
117−constTy (B16V _) = "Bits16x8"
118−constTy (B32V _) = "Bits32x4"
119−constTy (B64V _) = "Bits64x2"
120116constTy _ = "Type"
121117
122118instance SExpable OutputAnnotation where
src/Idris/ParseExpr.hs+3−8
@@ -1156,21 +1156,16 @@ constants =
11561156 [ ("Integer", AType (ATInt ITBig))
11571157 , ("Int", AType (ATInt ITNative))
11581158 , ("Char", AType (ATInt ITChar))
1159− , ("Float", AType ATFloat)
1159+ , ("Double", AType ATFloat)
11601160 , ("String", StrType)
1161− , ("Ptr", PtrType)
1162− , ("ManagedPtr", ManagedPtrType)
1161+-- , ("Ptr", PtrType)
1162+-- , ("ManagedPtr", ManagedPtrType)
11631163 , ("prim__WorldType", WorldType)
11641164 , ("prim__TheWorld", TheWorld)
1165− , ("prim__UnsafeBuffer", BufferType)
11661165 , ("Bits8", AType (ATInt (ITFixed IT8)))
11671166 , ("Bits16", AType (ATInt (ITFixed IT16)))
11681167 , ("Bits32", AType (ATInt (ITFixed IT32)))
11691168 , ("Bits64", AType (ATInt (ITFixed IT64)))
1170− , ("Bits8x16", AType (ATInt (ITVec IT8 16)))
1171− , ("Bits16x8", AType (ATInt (ITVec IT16 8)))
1172− , ("Bits32x4", AType (ATInt (ITVec IT32 4)))
1173− , ("Bits64x2", AType (ATInt (ITVec IT64 2)))
11741169 ]
11751170
11761171constant :: IdrisParser Idris.Core.TT.Const
src/Idris/Parser.hs+54−7
@@ -59,6 +59,7 @@ import Data.List
5959import Data.Monoid
6060import Data.Char
6161import Data.Ord
62+import Data.Generics.Uniplate.Data (descendM)
6263import qualified Data.Map as M
6364import qualified Data.HashSet as HS
6465import qualified Data.Text as T
@@ -276,7 +277,7 @@ syntaxRule syn
276277 when (length ns /= length (nub ns))
277278 $ unexpected "repeated variable in syntax rule"
278279 lchar '='
279− tm <- typeExpr (allowImp syn)
280+ tm <- typeExpr (allowImp syn) >>= uniquifyBinders [n | Binding n <- syms]
280281 terminator
281282 return (Rule (mkSimple syms) tm sty)
282283 where
@@ -297,7 +298,51 @@ syntaxRule syn
297298 where ts = dropWhile isSpace . dropWhileEnd isSpace $ s
298299 mkSimple' (e : es) = e : mkSimple' es
299300 mkSimple' [] = []
300−
301+
302+ -- Prevent syntax variable capture by making all binders under syntax unique
303+ -- (the ol' Common Lisp GENSYM approach)
304+ uniquifyBinders :: [Name] -> PTerm -> IdrisParser PTerm
305+ uniquifyBinders userNames = fixBind []
306+ where
307+ fixBind :: [(Name, Name)] -> PTerm -> IdrisParser PTerm
308+ fixBind rens (PRef fc n) | Just n' <- lookup n rens =
309+ return $ PRef fc n'
310+ fixBind rens (PPatvar fc n) | Just n' <- lookup n rens =
311+ return $ PPatvar fc n'
312+ fixBind rens (PLam fc n ty body)
313+ | n `elem` userNames = liftM2 (PLam fc n) (fixBind rens ty) (fixBind rens body)
314+ | otherwise =
315+ do ty' <- fixBind rens ty
316+ n' <- gensym n
317+ body' <- fixBind ((n,n'):rens) body
318+ return $ PLam fc n' ty' body'
319+ fixBind rens (PPi plic n argTy body)
320+ | n `elem` userNames = liftM2 (PPi plic n) (fixBind rens argTy) (fixBind rens body)
321+ | otherwise =
322+ do ty' <- fixBind rens argTy
323+ n' <- gensym n
324+ body' <- fixBind ((n,n'):rens) body
325+ return $ (PPi plic n' ty' body')
326+ fixBind rens (PLet fc n ty val body)
327+ | n `elem` userNames = liftM3 (PLet fc n)
328+ (fixBind rens ty)
329+ (fixBind rens val)
330+ (fixBind rens body)
331+ | otherwise =
332+ do ty' <- fixBind rens ty
333+ val' <- fixBind rens val
334+ n' <- gensym n
335+ body' <- fixBind ((n,n'):rens) body
336+ return $ (PLet fc n' ty' val' body')
337+ fixBind rens (PMatchApp fc n) | Just n' <- lookup n rens =
338+ return $ PMatchApp fc n'
339+ fixBind rens x = descendM (fixBind rens) x
340+
341+ gensym :: Name -> IdrisParser Name
342+ gensym n = do ist <- get
343+ let idx = idris_name ist
344+ put ist { idris_name = idx + 1 }
345+ return $ sMN idx (show n)
301346
302347{- | Parses a syntax symbol (either binding variable, keyword or expression)
303348
@@ -455,10 +500,11 @@ Postulate ::=
455500@
456501-}
457502postulate :: SyntaxInfo -> IdrisParser PDecl
458−postulate syn = do doc <- try $ do (doc, _) <- docstring syn
503+postulate syn = do (doc, ext)
504+ <- try $ do (doc, _) <- docstring syn
459505 pushIndent
460− reserved "postulate"
461− return doc
506+ ext <- ppostDecl
507+ return (doc, ext)
462508 ist <- get
463509 let initOpts = if default_total ist
464510 then [TotalFn]
@@ -473,9 +519,10 @@ postulate syn = do doc <- try $ do (doc, _) <- docstring syn
473519 fc <- getFC
474520 terminator
475521 addAcc n acc
476− return (PPostulate doc syn fc opts' n ty)
522+ return (PPostulate ext doc syn fc opts' n ty)
477523 <?> "postulate"
478−
524+ where ppostDecl = do reserved "postulate"; return False
525+ <|> do lchar '%'; reserved "extern"; return True
479526{- | Parses a using declaration
480527
481528@
src/Idris/Primitives.hs+23−261
@@ -13,7 +13,6 @@ import Data.Word
1313import Data.Int
1414import Data.Char
1515import Data.Function (on)
16−import Data.Vector.Unboxed (Vector)
1716import qualified Data.Vector.Unboxed as V
1817
1918data Prim = Prim { p_name :: Name,
@@ -167,43 +166,32 @@ primitives =
167166 Prim (sUN "prim__strRev") (ty [StrType] StrType) 1 (p_strRev)
168167 (1, LStrRev) total,
169168
170− Prim (sUN "prim__readFile") (ty [WorldType,PtrType] StrType) 2 (p_cantreduce)
171− (2, LReadFile) total, -- total is okay, because we have 'WorldType'
172− Prim (sUN "prim__writeFile") (ty [WorldType,PtrType,StrType] (AType (ATInt ITNative))) 3 (p_cantreduce)
173− (3, LWriteFile) total,
174− Prim (sUN "prim__readString") (ty [WorldType] StrType) 1 (p_cantreduce)
175− (1, LReadStr) total, -- total is okay, because we have 'WorldType'
176− Prim (sUN "prim__writeString") (ty [WorldType,StrType] (AType (ATInt ITNative))) 2 (p_cantreduce)
177− (2, LWriteStr) total,
178−
179− Prim (sUN "prim__vm") (ty [] PtrType) 0 (p_cantreduce)
180− (0, LVMPtr) total,
181− -- Streams
182− Prim (sUN "prim__stdin") (ty [] PtrType) 0 (p_cantreduce)
183− (0, LStdIn) total,
184− Prim (sUN "prim__stdout") (ty [] PtrType) 0 (p_cantreduce)
185− (0, LStdOut) total,
186− Prim (sUN "prim__stderr") (ty [] PtrType) 0 (p_cantreduce)
187− (0, LStdErr) total,
188− Prim (sUN "prim__null") (ty [] PtrType) 0 (p_cantreduce)
189− (0, LNullPtr) total,
190− -- Managed pointer registration
191− Prim (sUN "prim__registerPtr") (ty [PtrType, AType (ATInt ITNative)] ManagedPtrType) 2 (p_cantreduce)
192− (2, LRegisterPtr) total,
193− -- Buffers
194− Prim (sUN "prim__allocate") (ty [AType (ATInt (ITFixed IT64))] BufferType) 1 (p_allocate)
195− (1, LAllocate) total,
196− Prim (sUN "prim__appendBuffer") (ty [BufferType, AType (ATInt (ITFixed IT64)), AType (ATInt (ITFixed IT64)), AType (ATInt (ITFixed IT64)), AType (ATInt (ITFixed IT64)), BufferType] BufferType) 6 (p_appendBuffer)
197− (6, LAppendBuffer) partial,
169+-- Prim (sUN "prim__readFile") (ty [WorldType,PtrType] StrType) 2 (p_cantreduce)
170+-- (2, LReadFile) total, -- total is okay, because we have 'WorldType'
171+-- Prim (sUN "prim__writeFile") (ty [WorldType,PtrType,StrType] (AType (ATInt ITNative))) 3 (p_cantreduce)
172+-- (3, LWriteFile) total,
173+-- Prim (sUN "prim__readString") (ty [WorldType] StrType) 1 (p_cantreduce)
174+-- (1, LReadStr) total, -- total is okay, because we have 'WorldType'
175+-- Prim (sUN "prim__writeString") (ty [WorldType,StrType] (AType (ATInt ITNative))) 2 (p_cantreduce)
176+-- (2, LWriteStr) total,
177+--
178+-- Prim (sUN "prim__vm") (ty [] PtrType) 0 (p_cantreduce)
179+-- (0, LVMPtr) total,
180+-- -- Streams
181+-- Prim (sUN "prim__stdin") (ty [] PtrType) 0 (p_cantreduce)
182+-- (0, LStdIn) total,
183+-- Prim (sUN "prim__stdout") (ty [] PtrType) 0 (p_cantreduce)
184+-- (0, LStdOut) total,
185+-- Prim (sUN "prim__stderr") (ty [] PtrType) 0 (p_cantreduce)
186+-- (0, LStdErr) total,
187+-- Prim (sUN "prim__null") (ty [] PtrType) 0 (p_cantreduce)
188+-- (0, LNullPtr) total,
189+-- -- Managed pointer registration
190+-- Prim (sUN "prim__registerPtr") (ty [PtrType, AType (ATInt ITNative)] ManagedPtrType) 2 (p_cantreduce)
191+-- (2, LRegisterPtr) total,
198192 Prim (sUN "prim__systemInfo") (ty [AType (ATInt ITNative)] StrType) 1 (p_cantreduce)
199193 (1, LSystemInfo) total
200194 ] ++ concatMap intOps [ITFixed IT8, ITFixed IT16, ITFixed IT32, ITFixed IT64, ITBig, ITNative, ITChar]
201− ++ concatMap vecOps vecTypes
202− ++ concatMap fixedOps [ITFixed IT8, ITFixed IT16, ITFixed IT32, ITFixed IT64] -- ITNative, ITChar, ATFloat ] ++ vecTypes
203− ++ vecBitcasts vecTypes
204−
205−vecTypes :: [IntTy]
206−vecTypes = [ITVec IT8 16, ITVec IT16 8, ITVec IT32 4, ITVec IT64 2]
207195
208196intOps :: IntTy -> [Prim]
209197intOps ity = intCmps ity ++ intArith ity ++ intConv ity
@@ -257,67 +245,11 @@ intConv ity =
257245 (1, LFloatInt ity) total
258246 ]
259247
260−vecCmps :: IntTy -> [Prim]
261−vecCmps ity =
262− [ iCmp ity "slt" True (bCmp ity (<)) (LSLt . ATInt) total
263− , iCmp ity "slte" True (bCmp ity (<=)) (LSLe . ATInt) total
264− , iCmp ity "eq" True (bCmp ity (==)) (LEq . ATInt) total
265− , iCmp ity "sgte" True (bCmp ity (>=)) (LSGe . ATInt) total
266− , iCmp ity "sgt" True (bCmp ity (>)) (LSGt . ATInt) total
267− , iCmp ity "lt" True (bCmp ity (<)) LLt total
268− , iCmp ity "lte" True (bCmp ity (<=)) LLe total
269− , iCmp ity "gte" True (bCmp ity (>=)) LGe total
270− , iCmp ity "gt" True (bCmp ity (>)) LGt total
271− ]
272−
273−-- The TODOs in this function are documented as Issue #1617 on the issue tracker.
274−--
275−-- https://github.com/idris-lang/Idris-dev/issues/1617
276−vecOps :: IntTy -> [Prim]
277−vecOps ity@(ITVec elem count) =
278− [ Prim (sUN $ "prim__mk" ++ intTyName ity)
279− (ty (replicate count . AType . ATInt . ITFixed $ elem) (AType . ATInt $ ity))
280− count (mkVecCon elem count) (count, LMkVec elem count) total
281− , Prim (sUN $ "prim__index" ++ intTyName ity)
282− (ty [AType . ATInt $ ity, AType (ATInt (ITFixed IT32))] (AType . ATInt . ITFixed $ elem))
283− 2 (mkVecIndex count) (2, LIdxVec elem count) partial -- TODO: Ensure this reduces
284− , Prim (sUN $ "prim__update" ++ intTyName ity)
285− (ty [AType . ATInt $ ity, AType (ATInt (ITFixed IT32)), AType . ATInt . ITFixed $ elem]
286− (AType . ATInt $ ity))
287− 3 (mkVecUpdate elem count) (3, LUpdateVec elem count) partial -- TODO: Ensure this reduces
288− ] ++ intArith ity ++ vecCmps ity
289−
290248bitcastPrim :: ArithTy -> ArithTy -> (ArithTy -> [Const] -> Maybe Const) -> PrimFn -> Prim
291249bitcastPrim from to impl prim =
292250 Prim (sUN $ "prim__bitcast" ++ aTyName from ++ "_" ++ aTyName to) (ty [AType from] (AType to)) 1 (impl to)
293251 (1, prim) total
294252
295−vecBitcasts :: [IntTy] -> [Prim]
296−vecBitcasts tys = [bitcastPrim from to bitcastVec (LBitCast from to)
297− | from <- map ATInt vecTypes, to <- map ATInt vecTypes, from /= to]
298−
299−fixedOps :: IntTy -> [Prim]
300−fixedOps ity@(ITFixed _) =
301− map appendFun endiannesses ++
302− map peekFun endiannesses
303− where
304− endiannesses = [ Native, LE, BE ]
305− tyName = intTyName ity
306− b64 = AType (ATInt (ITFixed IT64))
307− thisTy = AType $ ATInt ity
308− appendFun en = Prim (sUN $ "prim__append" ++ tyName ++ show en)
309− (ty [BufferType, b64, b64, thisTy] BufferType)
310− 4 (p_append en) (4, LAppend ity en) partial
311− peekFun en = Prim (sUN $ "prim__peek" ++ tyName ++ show en)
312− (ty [BufferType, b64] thisTy)
313− 2 (p_peek ity en) (2, LPeek ity en) partial
314−
315−mapHalf :: (V.Unbox a, V.Unbox b) => ((a, a) -> b) -> Vector a -> Vector b
316−mapHalf f xs = V.generate (V.length xs `div` 2) (\i -> f (xs V.! (i*2), xs V.! (i*2+1)))
317−
318−mapDouble :: (V.Unbox a, V.Unbox b) => (Bool -> a -> b) -> Vector a -> Vector b
319−mapDouble f xs = V.generate (V.length xs * 2) (\i -> f (i `rem` 2 == 0) (xs V.! (i `div` 2)))
320−
321253concatWord8 :: (Word8, Word8) -> Word16
322254concatWord8 (high, low) = fromIntegral high .|. (fromIntegral low `shiftL` 8)
323255
@@ -339,76 +271,6 @@ truncWord64 :: Bool -> Word64 -> Word32
339271truncWord64 True x = fromIntegral (x `shiftR` 32)
340272truncWord64 False x = fromIntegral x
341273
342−bitcastVec :: ArithTy -> [Const] -> Maybe Const
343−bitcastVec (ATInt (ITVec IT8 n)) [x@(B8V v)]
344− | V.length v == n = Just x
345−bitcastVec (ATInt (ITVec IT16 n)) [B8V v]
346− | V.length v == n*2 = Just . B16V . mapHalf concatWord8 $ v
347−bitcastVec (ATInt (ITVec IT32 n)) [B8V v]
348− | V.length v == n*4 = Just . B32V . mapHalf concatWord16 . mapHalf concatWord8 $ v
349−bitcastVec (ATInt (ITVec IT64 n)) [B8V v]
350− | V.length v == n*8 = Just . B64V . mapHalf concatWord32 . mapHalf concatWord16 . mapHalf concatWord8 $ v
351−
352−bitcastVec (ATInt (ITVec IT8 n)) [B16V v]
353− | V.length v * 2 == n = Just . B8V . mapDouble truncWord16 $ v
354−bitcastVec (ATInt (ITVec IT16 n)) [x@(B16V v)]
355− | V.length v == n = Just x
356−bitcastVec (ATInt (ITVec IT32 n)) [B16V v]
357− | V.length v == n*2 = Just . B32V . mapHalf concatWord16 $ v
358−bitcastVec (ATInt (ITVec IT64 n)) [B16V v]
359− | V.length v == n*4 = Just . B64V . mapHalf concatWord32 . mapHalf concatWord16 $ v
360−
361−bitcastVec (ATInt (ITVec IT8 n)) [B32V v]
362− | V.length v * 4 == n = Just . B8V . mapDouble truncWord16 . mapDouble truncWord32 $ v
363−bitcastVec (ATInt (ITVec IT16 n)) [B32V v]
364− | V.length v * 2 == n = Just . B16V . mapDouble truncWord32 $ v
365−bitcastVec (ATInt (ITVec IT32 n)) [x@(B32V v)]
366− | V.length v == n = Just x
367−bitcastVec (ATInt (ITVec IT64 n)) [B32V v]
368− | V.length v == n*2 = Just . B64V . mapHalf concatWord32 $ v
369−
370−bitcastVec (ATInt (ITVec IT8 n)) [B64V v]
371− | V.length v * 8 == n = Just . B8V . mapDouble truncWord16 . mapDouble truncWord32 . mapDouble truncWord64 $ v
372−bitcastVec (ATInt (ITVec IT16 n)) [B64V v]
373− | V.length v * 4 == n = Just . B16V . mapDouble truncWord32 . mapDouble truncWord64 $ v
374−bitcastVec (ATInt (ITVec IT32 n)) [B64V v]
375− | V.length v == n*2 = Just . B32V . mapDouble truncWord64 $ v
376−bitcastVec (ATInt (ITVec IT64 n)) [x@(B64V v)]
377− | V.length v == n = Just x
378−
379−bitcastVec _ _ = Nothing
380−
381−mkVecCon :: NativeTy -> Int -> [Const] -> Maybe Const
382−mkVecCon ity count args
383− | length ints == count = Just (mkVec ity count ints)
384− | otherwise = Nothing
385− where
386− ints = getInt args
387− mkVec :: NativeTy -> Int -> [Integer] -> Const
388− mkVec IT8 len values = B8V $ V.generate len (fromInteger . (values !!))
389− mkVec IT16 len values = B16V $ V.generate len (fromInteger . (values !!))
390− mkVec IT32 len values = B32V $ V.generate len (fromInteger . (values !!))
391− mkVec IT64 len values = B64V $ V.generate len (fromInteger . (values !!))
392−
393−mkVecIndex count [vec, B32 i] = Just (idxVec vec)
394− where
395− idxVec :: Const -> Const
396− idxVec (B8V v) = B8 $ V.unsafeIndex v (fromIntegral i)
397− idxVec (B16V v) = B16 $ V.unsafeIndex v (fromIntegral i)
398− idxVec (B32V v) = B32 $ V.unsafeIndex v (fromIntegral i)
399− idxVec (B64V v) = B64 $ V.unsafeIndex v (fromIntegral i)
400−mkVecIndex _ _ = Nothing
401−
402−mkVecUpdate ity count [vec, B32 i, newElem] = updateVec vec newElem
403− where
404− updateVec :: Const -> Const -> Maybe Const
405− updateVec (B8V v) (B8 e) = Just . B8V $ V.unsafeUpdate v (V.singleton (fromIntegral i, e))
406− updateVec (B16V v) (B16 e) = Just . B16V $ V.unsafeUpdate v (V.singleton (fromIntegral i, e))
407− updateVec (B32V v) (B32 e) = Just . B32V $ V.unsafeUpdate v (V.singleton (fromIntegral i, e))
408− updateVec (B64V v) (B64 e) = Just . B64V $ V.unsafeUpdate v (V.singleton (fromIntegral i, e))
409− updateVec _ _ = Nothing
410−mkVecUpdate _ _ _ = Nothing
411−
412274aTyName :: ArithTy -> String
413275aTyName (ATInt t) = intTyName t
414276aTyName ATFloat = "Float"
@@ -470,18 +332,6 @@ bsrem (ITFixed IT64) [B64 x, B64 y]
470332 = Just $ B64 (fromIntegral (fromIntegral x `rem` fromIntegral y :: Int64))
471333bsrem ITNative [I x, I y] = Just $ I (x `rem` y)
472334bsrem ITChar [Ch x, Ch y] = Just $ Ch (chr $ (ord x) `rem` (ord y))
473−bsrem (ITVec IT8 _) [B8V x, B8V y]
474− = Just . B8V $
475− V.zipWith (\n d -> (fromIntegral (fromIntegral n `rem` fromIntegral d :: Int8))) x y
476−bsrem (ITVec IT16 _) [B16V x, B16V y]
477− = Just . B16V $
478− V.zipWith (\n d -> (fromIntegral (fromIntegral n `rem` fromIntegral d :: Int16))) x y
479−bsrem (ITVec IT32 _) [B32V x, B32V y]
480− = Just . B32V $
481− V.zipWith (\n d -> (fromIntegral (fromIntegral n `rem` fromIntegral d :: Int64))) x y
482−bsrem (ITVec IT64 _) [B64V x, B64V y]
483− = Just . B64V $
484− V.zipWith (\n d -> (fromIntegral (fromIntegral n `rem` fromIntegral d :: Int64))) x y
485335bsrem _ _ = Nothing
486336
487337bsdiv :: IntTy -> [Const] -> Maybe Const
@@ -496,18 +346,6 @@ bsdiv (ITFixed IT64) [B64 x, B64 y]
496346 = Just $ B64 (fromIntegral (fromIntegral x `div` fromIntegral y :: Int64))
497347bsdiv ITNative [I x, I y] = Just $ I (x `div` y)
498348bsdiv ITChar [Ch x, Ch y] = Just $ Ch (chr $ (ord x) `div` (ord y))
499−bsdiv (ITVec IT8 _) [B8V x, B8V y]
500− = Just . B8V $
501− V.zipWith (\n d -> (fromIntegral (fromIntegral n `div` fromIntegral d :: Int8))) x y
502−bsdiv (ITVec IT16 _) [B16V x, B16V y]
503− = Just . B16V $
504− V.zipWith (\n d -> (fromIntegral (fromIntegral n `div` fromIntegral d :: Int16))) x y
505−bsdiv (ITVec IT32 _) [B32V x, B32V y]
506− = Just . B32V $
507− V.zipWith (\n d -> (fromIntegral (fromIntegral n `div` fromIntegral d :: Int64))) x y
508−bsdiv (ITVec IT64 _) [B64V x, B64V y]
509− = Just . B64V $
510− V.zipWith (\n d -> (fromIntegral (fromIntegral n `div` fromIntegral d :: Int64))) x y
511349bsdiv _ _ = Nothing
512350
513351bashr :: IntTy -> [Const] -> Maybe Const
@@ -522,18 +360,6 @@ bashr (ITFixed IT64) [B64 x, B64 y]
522360 = Just $ B64 (fromIntegral (fromIntegral x `shiftR` fromIntegral y :: Int64))
523361bashr ITNative [I x, I y] = Just $ I (x `shiftR` y)
524362bashr ITChar [Ch x, Ch y] = Just $ Ch (chr $ (ord x) `shiftR` (ord y))
525−bashr (ITVec IT8 _) [B8V x, B8V y]
526− = Just . B8V $
527− V.zipWith (\n d -> (fromIntegral (fromIntegral n `shiftR` fromIntegral d :: Int8))) x y
528−bashr (ITVec IT16 _) [B16V x, B16V y]
529− = Just . B16V $
530− V.zipWith (\n d -> (fromIntegral (fromIntegral n `shiftR` fromIntegral d :: Int16))) x y
531−bashr (ITVec IT32 _) [B32V x, B32V y]
532− = Just . B32V $
533− V.zipWith (\n d -> (fromIntegral (fromIntegral n `shiftR` fromIntegral d :: Int64))) x y
534−bashr (ITVec IT64 _) [B64V x, B64V y]
535− = Just . B64V $
536− V.zipWith (\n d -> (fromIntegral (fromIntegral n `shiftR` fromIntegral d :: Int64))) x y
537363bashr _ _ = Nothing
538364
539365bUn :: IntTy -> (forall a. Bits a => a -> a) -> [Const] -> Maybe Const
@@ -544,10 +370,6 @@ bUn (ITFixed IT64) op [B64 x] = Just $ B64 (op x)
544370bUn ITBig op [BI x] = Just $ BI (op x)
545371bUn ITNative op [I x] = Just $ I (op x)
546372bUn ITChar op [Ch x] = Just $ Ch (chr $ op (ord x))
547−bUn (ITVec IT8 _) op [B8V x] = Just . B8V $ V.map op x
548−bUn (ITVec IT16 _) op [B16V x] = Just . B16V $ V.map op x
549−bUn (ITVec IT32 _) op [B32V x] = Just . B32V $ V.map op x
550−bUn (ITVec IT64 _) op [B64V x] = Just . B64V $ V.map op x
551373bUn _ _ _ = Nothing
552374
553375bitBin :: IntTy -> (forall a. (Bits a, Integral a) => a -> a -> a) -> [Const] -> Maybe Const
@@ -558,10 +380,6 @@ bitBin (ITFixed IT64) op [B64 x, B64 y] = Just $ B64 (op x y)
558380bitBin ITBig op [BI x, BI y] = Just $ BI (op x y)
559381bitBin ITNative op [I x, I y] = Just $ I (op x y)
560382bitBin ITChar op [Ch x, Ch y] = Just $ Ch (chr $ op (ord x) (ord y))
561−bitBin (ITVec IT8 _) op [B8V x, B8V y] = Just . B8V $ V.zipWith op x y
562−bitBin (ITVec IT16 _) op [B16V x, B16V y] = Just . B16V $ V.zipWith op x y
563−bitBin (ITVec IT32 _) op [B32V x, B32V y] = Just . B32V $ V.zipWith op x y
564−bitBin (ITVec IT64 _) op [B64V x, B64V y] = Just . B64V $ V.zipWith op x y
565383bitBin _ _ _ = Nothing
566384
567385bCmp :: IntTy -> (forall a. (Integral a, Ord a) => a -> a -> Bool) -> [Const] -> Maybe Const
@@ -572,14 +390,6 @@ bCmp (ITFixed IT64) op [B64 x, B64 y] = Just $ I (if (op x y) then 1 else 0)
572390bCmp ITBig op [BI x, BI y] = Just $ I (if (op x y) then 1 else 0)
573391bCmp ITNative op [I x, I y] = Just $ I (if (op x y) then 1 else 0)
574392bCmp ITChar op [Ch x, Ch y] = Just $ I (if (op (ord x) (ord y)) then 1 else 0)
575−bCmp (ITVec IT8 _) op [B8V x, B8V y]
576− = Just . B8V . V.map (\b -> if b then -1 else 0) $ V.zipWith op x y
577−bCmp (ITVec IT16 _) op [B16V x, B16V y]
578− = Just . B16V . V.map (\b -> if b then -1 else 0) $ V.zipWith op x y
579−bCmp (ITVec IT32 _) op [B32V x, B32V y]
580− = Just . B32V . V.map (\b -> if b then -1 else 0) $ V.zipWith op x y
581−bCmp (ITVec IT64 _) op [B64V x, B64V y]
582− = Just . B64V . V.map (\b -> if b then -1 else 0) $ V.zipWith op x y
583393bCmp _ _ _ = Nothing
584394
585395
@@ -717,53 +527,5 @@ p_strCons _ = Nothing
717527p_strRev [Str xs] = Just $ Str (reverse xs)
718528p_strRev _ = Nothing
719529
720−p_allocate, p_appendBuffer :: [Const] -> Maybe Const
721−p_allocate [B64 _] = Just $ B8V V.empty
722−p_allocate n = Nothing
723−p_appendBuffer [B8V vect1, B64 size1, B64 count, B64 size2, B64 off, B8V vect2] =
724− Just $ B8V (foldl (V.++)
725− (V.slice 0 (fromIntegral size1) vect1)
726− (replicate (fromIntegral count) (V.slice (fromIntegral off) (fromIntegral size2) vect2)))
727−p_appendBuffer n = Nothing
728−p_append :: Endianness -> [Const] -> Maybe Const
729−p_append en [B8V vect, B64 size, B64 count, val] =
730− let bytes = case val of
731− B8 x -> [x]
732− B16 x -> [fromIntegral x, fromIntegral (shiftR x 8)]
733− B32 x -> map (fromIntegral . shiftR x) [0,8..24]
734− B64 x -> map (fromIntegral . shiftR x) [0,8..56]
735− in Just $ B8V (foldl V.snoc
736− (V.slice 0 (fromIntegral size) vect)
737− (concat (replicate (fromIntegral count)
738− (case en of
739− BE -> reverse bytes
740− _ -> bytes))))
741−p_append _ _ = Nothing
742−
743−p_peek :: IntTy -> Endianness -> [Const] -> Maybe Const
744−p_peek (ITFixed IT8) _ [B8V vect, B64 offset] = Just $ B8 (vect V.! fromIntegral offset)
745−p_peek (ITFixed IT16) en [B8V vect, B64 offset] =
746− let bytes = [0..1]
747− in Just $ B16 (foldl (\full byte -> shiftL full 8 .|. fromIntegral (vect V.! (fromIntegral offset+byte)))
748− 0
749− (case en of
750− BE -> bytes
751− _ -> reverse bytes))
752−p_peek (ITFixed IT32) en [B8V vect, B64 offset] =
753− let bytes = [0..1]
754− in Just $ B32 (foldl (\full byte -> shiftL full 8 .|. fromIntegral (vect V.! (fromIntegral offset+byte)))
755− 0
756− (case en of
757− BE -> bytes
758− _ -> reverse bytes))
759−p_peek (ITFixed IT64) en [B8V vect, B64 offset] =
760− let bytes = [0..1]
761− in Just $ B64 (foldl (\full byte -> shiftL full 8 .|. fromIntegral (vect V.! (fromIntegral offset+byte)))
762− 0
763− (case en of
764− BE -> bytes
765− _ -> reverse bytes))
766−p_peek _ _ _ = Nothing
767−
768530p_cantreduce :: a -> Maybe b
769531p_cantreduce _ = Nothing
src/Idris/Providers.hs+3−3
@@ -10,16 +10,16 @@ import Idris.Error
1010-- | Wrap a type provider in the type of type providers
1111providerTy :: FC -> PTerm -> PTerm
1212providerTy fc tm
13− = PApp fc (PRef fc $ sUN "Provider") [PExp 0 [] (sMN 0 "pvarg") tm]
13+ = PApp fc (PRef fc $ sNS (sUN "Provider" ) ["Providers", "Prelude"]) [PExp 0 [] (sMN 0 "pvarg") tm]
1414
1515ioret :: Name
1616ioret = sUN "prim_io_return"
1717
1818ermod :: Name
19−ermod = sNS (sUN "Error") ["Providers"]
19+ermod = sNS (sUN "Error") ["Providers", "Prelude"]
2020
2121prmod :: Name
22−prmod = sNS (sUN "Provide") ["Providers"]
22+prmod = sNS (sUN "Provide") ["Providers", "Prelude"]
2323
2424data Provided a = Provide a
2525 deriving (Show, Eq, Functor)
src/Idris/REPL.hs+16−4
@@ -87,6 +87,7 @@ import Control.Concurrent
8787import Data.Maybe
8888import Data.List hiding (group)
8989import Data.Char
90+import qualified Data.Set as S
9091import Data.Version
9192import Data.Word (Word)
9293import Data.Either (partitionEithers)
@@ -945,9 +946,10 @@ process fn (DocStr (Right c) _) -- constants only have overviews
945946process fn Universes
946947 = do i <- getIState
947948 let cs = idris_constraints i
949+ let cslist = S.toAscList cs
948950-- iputStrLn $ showSep "\n" (map show cs)
949− iputStrLn $ show (map fst cs)
950− let n = length cs
951+ iputStrLn $ show (map uconstraint cslist)
952+ let n = length cslist
951953 iputStrLn $ "(" ++ show n ++ " constraints)"
952954 case ucheck cs of
953955 Error e -> iPrintError $ pshow i e
@@ -1518,7 +1520,8 @@ loadInputs inputs toline -- furthest line to read in input source files
15181520
15191521idrisMain :: [Opt] -> Idris ()
15201522idrisMain opts =
1521− do let inputs = opt getFile opts
1523+ do mapM_ setWidth (opt getConsoleWidth opts)
1524+ let inputs = opt getFile opts
15221525 let quiet = Quiet `elem` opts
15231526 let nobanner = NoBanner `elem` opts
15241527 let idesl = Idemode `elem` opts || IdemodeSocket `elem` opts
@@ -1533,6 +1536,7 @@ idrisMain opts =
15331536 let optimise = case opt getOptLevel opts of
15341537 [] -> 2
15351538 xs -> last xs
1539+
15361540 setOptLevel optimise
15371541 let outty = case opt getOutputTy opts of
15381542 [] -> if Interface `elem` opts then
@@ -1554,7 +1558,9 @@ idrisMain opts =
15541558 when (DefaultTotal `elem` opts) $ do i <- getIState
15551559 putIState (i { default_total = True })
15561560 setColourise $ not quiet && last (True : opt getColour opts)
1557− when (not runrepl) $ setWidth InfinitelyWide
1561+
1562+
1563+
15581564 mapM_ addLangExt (opt getLanguageExt opts)
15591565 setREPL runrepl
15601566 setQuiet (quiet || isJust script || not (null immediate))
@@ -1777,6 +1783,12 @@ getCodegen :: Opt -> Maybe Codegen
17771783getCodegen (UseCodegen x) = Just x
17781784getCodegen _ = Nothing
17791785
1786+
1787+getConsoleWidth :: Opt -> Maybe ConsoleWidth
1788+getConsoleWidth (UseConsoleWidth x) = Just x
1789+getConsoleWidth _ = Nothing
1790+
1791+
17801792getExecScript :: Opt -> Maybe String
17811793getExecScript (InterpretScript expr) = Just expr
17821794getExecScript _ = Nothing
test/basic006/run+3−2
@@ -1,5 +1,6 @@
11#!/usr/bin/env bash
2−idris $@ test020.idr -o test020
3−idris $@ test020a.idr --check --nocolor
2+
3+idris --consolewidth 80 $@ test020.idr -o test020
4+idris --consolewidth 80 $@ test020a.idr --check --nocolor
45./test020
56rm -f test020 *.ibc
test/basic009/run+6−3
@@ -1,5 +1,8 @@
11#!/usr/bin/env bash
2−idris $@ Main.idr --nocolour --check && echo MAIN-PASS
3−idris $@ Faulty.idr --nocolour --check && echo FAULTY-PASS
4−idris $@ Multiple.idr --nocolour --check && echo MULTIPLE-PASS
2+
3+idris --consolewidth 80 $@ Main.idr --nocolour --check && echo MAIN-PASS
4+idris --consolewidth 80 $@ Faulty.idr --nocolour --check && echo FAULTY-PASS
5+idris --consolewidth 80 $@ Multiple.idr --nocolour --check && echo MULTIPLE-PASS
6+
7+
58rm -f *.ibc B/*.ibc
test/basic011/run+1−1
@@ -1,4 +1,4 @@
11#!/usr/bin/env bash
2−idris $@ basic011.idr -o basic011
2+idris $@ basic011.idr -p contrib -o basic011
33./basic011
44rm -f basic011 *.ibc
test/basic013/basic013.idrnew file+34
@@ -0,0 +1,34 @@
1+foo : String
2+foo = "λx→x"
3+
4+bar : String
5+bar = "λx→x"
6+
7+baz : Char
8+baz = 'λ'
9+
10+quux : String
11+quux = "\x0a\x80\xC9\xFF\n3\n4"
12+
13+appMany : Nat -> String
14+appMany Z = foo
15+appMany (S k) = bar ++ appMany k
16+
17+main : IO ()
18+main = do putStrLn foo
19+ putStrLn (foo ++ bar)
20+ putStrLn (reverse (foo ++ bar))
21+ printLn (length foo)
22+ printLn baz
23+ let x = 4
24+ let newstr = appMany (toNat x)
25+ putStrLn newstr
26+ printLn (strHead newstr)
27+ printLn (length newstr)
28+ printLn (strIndex newstr 4)
29+ putStrLn (strCons (strIndex newstr 4) "")
30+ putStrLn ("Tail: " ++ strTail newstr)
31+ putStrLn ("Tail Tail: " ++ strTail (strTail newstr))
32+ putStrLn ("Cons: " ++ strCons 'λ' newstr)
33+ putStrLn ("Reverse: " ++ reverse newstr)
34+
test/basic013/expectednew file+14
@@ -0,0 +1,14 @@
1+λx→x
2+λx→xλx→x
3+x→xλx→xλ
4+4
5+'\955'
6+λx→xλx→xλx→xλx→xλx→x
7+'\955'
8+20
9+'\955'
10+λ
11+Tail: x→xλx→xλx→xλx→xλx→x
12+Tail Tail: →xλx→xλx→xλx→xλx→x
13+Cons: λλx→xλx→xλx→xλx→xλx→x
14+Reverse: x→xλx→xλx→xλx→xλx→xλ
test/basic013/runnew file+4
@@ -0,0 +1,4 @@
1+#!/usr/bin/env bash
2+idris $@ basic013.idr -o basic013
3+./basic013
4+rm -f basic013 *.ibc
test/docs001/expected+1−2
@@ -1,5 +1,5 @@
11Type checking ./docs001.idr
2−*docs001> Type class C
2+Type class C
33 class
44
55Parameters:
@@ -15,4 +15,3 @@ Instances:
1515 C (D a b)
1616 another instance of class
1717 a -- parameter type
18−*docs001> Bye bye
test/docs001/run+1−1
@@ -1,3 +1,3 @@
11#!/usr/bin/env bash
2−idris --nobanner --nocolor docs001.idr < input
2+idris --quiet --nocolor --consolewidth 80 docs001.idr < input
33rm *.ibc
test/docs002/docs002.idr−3
@@ -1,9 +1,6 @@
11module Main
22
33-- Simple test case for type provider documentation.
4−
5−import Providers
6−
74%language TypeProviders
85
96getType : Int -> IO (Provider Type)
test/docs002/run+1−1
@@ -1,3 +1,3 @@
11#!/usr/bin/env bash
2−idris --nobanner --nocolor docs002.idr < input
2+idris --consolewidth 80 --nobanner --nocolor docs002.idr < input
33rm *.ibc
test/docs003/docs003.idrnew file+9
@@ -0,0 +1,9 @@
1+module docs003
2+
3+instance [mine] Functor List where
4+ map m [] = []
5+ map m (x :: xs) = m x :: map m xs
6+
7+||| More functors!
8+instance [another] Functor List where
9+ map f xs = map @{mine} f xs
test/docs003/expectednew file+37
@@ -0,0 +1,37 @@
1+Type checking ./docs003.idr
2+Type class Functor
3+ Functors
4+
5+Parameters:
6+ f -- the action of the functor on objects
7+
8+Methods:
9+ map : Functor f => (m : a -> b) -> f a -> f b
10+ The action of the functor on morphisms
11+
12+Instances:
13+ Functor List
14+ Functor Stream
15+ Functor Provider
16+ Functor Binder
17+ Functor PrimIO
18+ Functor (IO' ffi)
19+ Functor Maybe
20+ Functor (Either e)
21+
22+Named instances:
23+ docs003.mine : Functor List
24+ docs003.another : Functor List
25+ More functors!
26+
27+Subclasses:
28+ Traversable f
29+ Applicative f
30+Named instance:
31+ mine : Functor List
32+
33+
34+Named instance:
35+ another : Functor List
36+ More functors!
37+
test/docs003/inputnew file+3
@@ -0,0 +1,3 @@
1+:doc Functor
2+:doc mine
3+:doc another
test/docs003/runnew file+3
@@ -0,0 +1,3 @@
1+#!/usr/bin/env bash
2+idris --consolewidth 80 --quiet --nocolor docs003.idr < input
3+rm *.ibc
test/error001/expected+9−1
@@ -1 +1,9 @@
1−test002.idr:5:6:Universe inconsistency
1+test002.idr:1:6:Universe inconsistency.
2+Working on: z
3+Old domain: Domain 6 6
4+New domain: Domain 6 5
5+Involved constraints:
6+ ConstraintFC {uconstraint = z <= a1, ufc = test002.idr:1:6}
7+ ConstraintFC {uconstraint = y < z, ufc = test002.idr:1:6}
8+ ConstraintFC {uconstraint = z <= a1, ufc = test002.idr:1:6}
9+
test/error003/expected+2−1
@@ -1,2 +1,3 @@
1−ErrorReflection.idr:68:5:When elaborating right hand side of bad:
1+ErrorReflection.idr:68:5:
2+When elaborating right hand side of bad:
23DSL type error: (t(503) => t'(504)) doesn't match ()
test/error003/run+1−1
@@ -1,3 +1,3 @@
11#!/usr/bin/env bash
2−idris $@ ErrorReflection.idr --nocolour --check
2+idris --consolewidth 80 $@ ErrorReflection.idr --nocolour --check
33rm -f *.ibc
test/error004/expected+6−3
@@ -1,6 +1,9 @@
1−FunErrTest.idr:35:10:When elaborating right hand side of badCadr1:
1+FunErrTest.idr:35:10:
2+When elaborating right hand side of badCadr1:
23When elaborating argument cons1 to function FunErrTest.cadr:
34 Could not prove that [] has at least two elements.
4−FunErrTest.idr:38:10:When elaborating right hand side of badCadr2:
5+FunErrTest.idr:38:10:
6+When elaborating right hand side of badCadr2:
57When elaborating argument cons2 to function FunErrTest.cadr:
6− Could not prove that tail [(fromInteger 1)] has at least two elements.
8+ Could not prove that tail [(fromInteger 1)] has at least two
9+ elements.
test/error004/run+1−1
@@ -1,3 +1,3 @@
11#!/usr/bin/env bash
2−idris $@ FunErrTest.idr --nocolour --check
2+idris --consolewidth 80 $@ FunErrTest.idr --nocolour --check
33rm -f *.ibc
test/error005/expected+2−1
@@ -13,7 +13,8 @@ When elaborating argument prf to function Data.Fin.fromInteger:
1313error005.idr:23:24:When elaborating right hand side of b0rken:
1414When elaborating argument prf to function Data.Fin.fromInteger:
1515 When using n as a literal for a Fin 3
16− Could not show that n is less than 3 because n is a bound variable instead of a constant Integer
16+ Could not show that n is less than 3 because n is a bound
17+ variable instead of a constant Integer
1718error005.idr:28:1:When elaborating right hand side of x:
1819When elaborating argument prf to function Data.Fin.fromInteger:
1920 When using 5 as a literal for a Fin 4
test/error005/run+1−1
@@ -1,3 +1,3 @@
11#!/usr/bin/env bash
2−idris $@ --check --nocolour error005.idr
2+idris --consolewidth 80 $@ --check --nocolour error005.idr
33rm -f *.ibc
test/ffi002/expected+1−1
@@ -1 +1 @@
1−test023.idr:22:21:Type provider error: Always fails
1+test023.idr:20:21:Type provider error: Always fails
test/ffi002/run+1−1
@@ -1,3 +1,3 @@
11#!/usr/bin/env bash
2−idris --quiet test023.idr -o test023
2+idris --consolewidth 80 --quiet test023.idr -o test023
33rm -f test023 *.ibc
test/ffi002/test023.idr−2
@@ -2,8 +2,6 @@ module Main
22
33-- Simple test case for trivial type providers.
44
5−import Providers
6−
75%language TypeProviders
86
97-- Provide the Unit type
test/ffi004/test026.idr−2
@@ -2,8 +2,6 @@ module Main
22
33-- Simple test case for trivial type providers.
44
5−import Providers
6−
75%language TypeProviders
86
97strToType : String -> Type
test/ffi005/Postulate.idr−2
@@ -1,7 +1,5 @@
11module Main
22
3−import Providers
4−
53%language TypeProviders
64
75bad : IO (Provider Type)
test/interactive007/run+1−1
@@ -1,2 +1,2 @@
11#!/usr/bin/env bash
2−idris --nobanner --nocolor < input
2+idris -p contrib --nobanner --nocolor < input
test/io003/run+2−2
@@ -1,6 +1,6 @@
11#!/usr/bin/env bash
2−idris $@ test018.idr -o test018
3−idris $@ test018a.idr -o test018a
2+idris $@ test018.idr -p contrib -o test018
3+idris $@ test018a.idr -p contrib -o test018a
44./test018
55#./test018a
66rm -f test018 test018a *.ibc
test/literate001/run+2−2
@@ -1,5 +1,5 @@
11#!/usr/bin/env bash
2−idris $@ test003a.lidr --check
3−idris $@ test003.lidr -o test003
2+idris --consolewidth 80 $@ test003a.lidr --check
3+idris --consolewidth 80 $@ test003.lidr -o test003
44./test003
55rm -f test003 test003.ibc Lit.ibc
test/primitives003/expected−2
@@ -16,8 +16,6 @@ True
1616False
1717True
1818False
19−True
20−False
2119False
2220True
2321False
test/primitives003/test038.idr−3
@@ -40,9 +40,6 @@ main = do
4040 -- Booleans
4141 putStrLn . show $ test True True
4242 putStrLn . show $ test True False
43− -- Float
44− putStrLn . show $ test 1.0 1.0
45− putStrLn . show $ test 1.0 2.0
4643 -- Maybe
4744 putStrLn . show $ test (Just "hello") (Just "hello")
4845 putStrLn . show $ test (Just "hello") (Just "world")
test/primitives004/expected → test/primitives004-disabled/expectedrenamed

The content is the same.

test/primitives004/primitives004.idr → test/primitives004-disabled/primitives004.idrrenamed

The content is the same.

test/primitives004/run → test/primitives004-disabled/runrenamed

The content is the same.

test/proof002/expected+2−1
@@ -1,4 +1,5 @@
1−Reflect.idr:208:38:When elaborating right hand side of testReflect1:
1+Reflect.idr:208:38:
2+When elaborating right hand side of testReflect1:
23When elaborating an application of function Reflect.getJust:
34 Can't unify
45 IsJust (Just x1) (Type of ItIsJust)
test/proof002/run+2−2
@@ -1,4 +1,4 @@
11#!/usr/bin/env bash
2−idris $@ test030.idr --check --nocolour
3−idris $@ test030a.idr --check --nocolour
2+idris --consolewidth 80 $@ test030.idr --check --nocolour
3+idris --consolewidth 80 $@ test030a.idr --check --nocolour
44rm -f *.ibc
test/proof007/expected+2−1
@@ -1,3 +1,4 @@
1−DefaultArgUnknownName.idr:9:6:When elaborating right hand side of test:
1+DefaultArgUnknownName.idr:9:6:
2+When elaborating right hand side of test:
23When elaborating argument arg to function DefaultArgUnknownName.funWithBadDefArg:
34 No such variable sadgjhsag
test/proof007/run+1−1
@@ -1,3 +1,3 @@
11#!/usr/bin/env bash
2−idris --check $@ DefaultArgUnknownName.idr
2+idris --consolewidth 80 --check $@ DefaultArgUnknownName.idr
33rm -f *.ibc
test/proof009/expectednew file+26
@@ -0,0 +1,26 @@
1+Type checking ./proof009.idr
2+
3+
4+---------- Goal: ----------
5+{hole0} : Int -> Int -> Int
6+-Main.arhs> ---------- Other goals: ----------
7+{hole0}
8+---------- Assumptions: ----------
9+ x : Int
10+---------- Goal: ----------
11+{hole1} : Int -> Int
12+-Main.arhs> ---------- Other goals: ----------
13+{hole1},{hole0}
14+---------- Assumptions: ----------
15+ x : Int
16+ y : Int
17+---------- Goal: ----------
18+{hole2} : Int
19+-Main.arhs> arhs: No more goals.
20+-Main.arhs> Proof completed!
21+Main.arhs = proof
22+ intro x
23+ intros
24+ trivial
25+
26+
test/proof009/inputnew file+6
@@ -0,0 +1,6 @@
1+:p arhs
2+intro x
3+intros
4+trivial
5+qed
6+:q
test/proof009/proof009.idrnew file+9
@@ -0,0 +1,9 @@
1+afn : Int -> Int -> Int
2+afn x y = ?arhs
3+
4+-- plus_comm_rhs_1 : y = plus y 0
5+--
6+-- plus_comm : (x, y : Nat) -> plus x y = plus y x
7+-- plus_comm Z y = plus_comm_rhs_1
8+-- plus_comm (S k) y = ?plus_comm_rhs_2
9+
test/proof009/runnew file+3
@@ -0,0 +1,3 @@
1+#!/usr/bin/env bash
2+idris $@ --quiet proof009.idr < input
3+rm -f *.ibc
test/quasiquote001/expected+2−2
@@ -1,5 +1,5 @@
11(App (App (App (P (DCon 1 3) (NS (UN ::) ["List", "Prelude"]) (Bind (UN a) (Pi (TType (UVar -1))) (Bind (MN 0 "_t") (Pi (V 0)) (Bind (MN 2 "_t") (Pi (App (P (TCon 0 0) (NS (UN List) ["List", "Prelude"]) Erased) (V 1))) (App (P (TCon 0 0) (NS (UN List) ["List", "Prelude"]) Erased) (V 2)))))) (P (TCon 8 0) (UN Unit) (TType (UVar -1)))) (P (DCon 0 0) (UN MkUnit) (P (TCon 0 0) (UN Unit) Erased))) (App (App (App (P (DCon 1 3) (NS (UN ::) ["List", "Prelude"]) (Bind (UN a) (Pi (TType (UVar -1))) (Bind (MN 0 "_t") (Pi (V 0)) (Bind (MN 2 "_t") (Pi (App (P (TCon 0 0) (NS (UN List) ["List", "Prelude"]) Erased) (V 1))) (App (P (TCon 0 0) (NS (UN List) ["List", "Prelude"]) Erased) (V 2)))))) (P (TCon 8 0) (UN Unit) (TType (UVar -1)))) (P (DCon 0 0) (UN MkUnit) (P (TCon 0 0) (UN Unit) Erased))) (App (P (DCon 0 1) (NS (UN Nil) ["List", "Prelude"]) (Bind (UN a) (Pi (TType (UVar -1))) (App (P (TCon 0 0) (NS (UN List) ["List", "Prelude"]) Erased) (V 0)))) (P (TCon 8 0) (UN Unit) (TType (UVar -1))))))
22--------------
3−(App (App (App (P (DCon 1 3) (NS (UN ::) ["List", "Prelude"]) (Bind (UN a) (Pi (TType (UVar -1))) (Bind (MN 0 "_t") (Pi (V 0)) (Bind (MN 2 "_t") (Pi (App (P (TCon 0 0) (NS (UN List) ["List", "Prelude"]) Erased) (V 1))) (App (P (TCon 0 0) (NS (UN List) ["List", "Prelude"]) Erased) (V 2)))))) (TType (UVar 32))) (TType (UVar 34))) (App (App (App (P (DCon 1 3) (NS (UN ::) ["List", "Prelude"]) (Bind (UN a) (Pi (TType (UVar -1))) (Bind (MN 0 "_t") (Pi (V 0)) (Bind (MN 2 "_t") (Pi (App (P (TCon 0 0) (NS (UN List) ["List", "Prelude"]) Erased) (V 1))) (App (P (TCon 0 0) (NS (UN List) ["List", "Prelude"]) Erased) (V 2)))))) (TType (UVar 36))) (App (App (App (App (P (DCon 0 4) (NS (UN MkPair) ["Builtins"]) (Bind (UN A) (Pi (TType (UVar -1))) (Bind (UN B) (Pi (TType (UVar -1))) (Bind (UN a) (Pi (V 1)) (Bind (UN b) (Pi (V 1)) (App (App (P (TCon 0 0) (NS (UN Pair) ["Builtins"]) Erased) (V 3)) (V 2))))))) (TType (UVar 30))) (TType (UVar 32))) (P (TCon 8 0) (NS (UN Nat) ["Nat", "Prelude"]) (TType (UVar -1)))) (P (TCon 8 0) (NS (UN Nat) ["Nat", "Prelude"]) (TType (UVar -1))))) (App (P (DCon 0 1) (NS (UN Nil) ["List", "Prelude"]) (Bind (UN a) (Pi (TType (UVar -1))) (App (P (TCon 0 0) (NS (UN List) ["List", "Prelude"]) Erased) (V 0)))) (TType (UVar 38)))))
3+(App (App (App (P (DCon 1 3) (NS (UN ::) ["List", "Prelude"]) (Bind (UN a) (Pi (TType (UVar -1))) (Bind (MN 0 "_t") (Pi (V 0)) (Bind (MN 2 "_t") (Pi (App (P (TCon 0 0) (NS (UN List) ["List", "Prelude"]) Erased) (V 1))) (App (P (TCon 0 0) (NS (UN List) ["List", "Prelude"]) Erased) (V 2)))))) (TType (UVar 24))) (TType (UVar 25))) (App (App (App (P (DCon 1 3) (NS (UN ::) ["List", "Prelude"]) (Bind (UN a) (Pi (TType (UVar -1))) (Bind (MN 0 "_t") (Pi (V 0)) (Bind (MN 2 "_t") (Pi (App (P (TCon 0 0) (NS (UN List) ["List", "Prelude"]) Erased) (V 1))) (App (P (TCon 0 0) (NS (UN List) ["List", "Prelude"]) Erased) (V 2)))))) (TType (UVar 26))) (App (App (App (App (P (DCon 0 4) (NS (UN MkPair) ["Builtins"]) (Bind (UN A) (Pi (TType (UVar -1))) (Bind (UN B) (Pi (TType (UVar -1))) (Bind (UN a) (Pi (V 1)) (Bind (UN b) (Pi (V 1)) (App (App (P (TCon 0 0) (NS (UN Pair) ["Builtins"]) Erased) (V 3)) (V 2))))))) (TType (UVar 22))) (TType (UVar 23))) (P (TCon 8 0) (NS (UN Nat) ["Nat", "Prelude"]) (TType (UVar -1)))) (P (TCon 8 0) (NS (UN Nat) ["Nat", "Prelude"]) (TType (UVar -1))))) (App (P (DCon 0 1) (NS (UN Nil) ["List", "Prelude"]) (Bind (UN a) (Pi (TType (UVar -1))) (App (P (TCon 0 0) (NS (UN List) ["List", "Prelude"]) Erased) (V 0)))) (TType (UVar 27)))))
44--------------
5−(App (App (App (App (P (DCon 0 4) (NS (UN MkPair) ["Builtins"]) (Bind (UN A) (Pi (TType (UVar -1))) (Bind (UN B) (Pi (TType (UVar -1))) (Bind (UN a) (Pi (V 1)) (Bind (UN b) (Pi (V 1)) (App (App (P (TCon 0 0) (NS (UN Pair) ["Builtins"]) Erased) (V 3)) (V 2))))))) (TType (UVar 30))) (TType (UVar 32))) (App (App (App (App (P (DCon 0 4) (NS (UN MkPair) ["Builtins"]) (Bind (UN A) (Pi (TType (UVar -1))) (Bind (UN B) (Pi (TType (UVar -1))) (Bind (UN a) (Pi (V 1)) (Bind (UN b) (Pi (V 1)) (App (App (P (TCon 0 0) (NS (UN Pair) ["Builtins"]) Erased) (V 3)) (V 2))))))) (TType (UVar 30))) (TType (UVar 32))) (TType (UVar 32))) (TType (UVar 32)))) (App (App (App (App (P (DCon 0 4) (NS (UN MkPair) ["Builtins"]) (Bind (UN A) (Pi (TType (UVar -1))) (Bind (UN B) (Pi (TType (UVar -1))) (Bind (UN a) (Pi (V 1)) (Bind (UN b) (Pi (V 1)) (App (App (P (TCon 0 0) (NS (UN Pair) ["Builtins"]) Erased) (V 3)) (V 2))))))) (TType (UVar 30))) (TType (UVar 32))) (TType (UVar 32))) (TType (UVar 32))))
5+(App (App (App (App (P (DCon 0 4) (NS (UN MkPair) ["Builtins"]) (Bind (UN A) (Pi (TType (UVar -1))) (Bind (UN B) (Pi (TType (UVar -1))) (Bind (UN a) (Pi (V 1)) (Bind (UN b) (Pi (V 1)) (App (App (P (TCon 0 0) (NS (UN Pair) ["Builtins"]) Erased) (V 3)) (V 2))))))) (TType (UVar 22))) (TType (UVar 23))) (App (App (App (App (P (DCon 0 4) (NS (UN MkPair) ["Builtins"]) (Bind (UN A) (Pi (TType (UVar -1))) (Bind (UN B) (Pi (TType (UVar -1))) (Bind (UN a) (Pi (V 1)) (Bind (UN b) (Pi (V 1)) (App (App (P (TCon 0 0) (NS (UN Pair) ["Builtins"]) Erased) (V 3)) (V 2))))))) (TType (UVar 22))) (TType (UVar 23))) (TType (UVar 24))) (TType (UVar 24)))) (App (App (App (App (P (DCon 0 4) (NS (UN MkPair) ["Builtins"]) (Bind (UN A) (Pi (TType (UVar -1))) (Bind (UN B) (Pi (TType (UVar -1))) (Bind (UN a) (Pi (V 1)) (Bind (UN b) (Pi (V 1)) (App (App (P (TCon 0 0) (NS (UN Pair) ["Builtins"]) Erased) (V 3)) (V 2))))))) (TType (UVar 22))) (TType (UVar 23))) (TType (UVar 24))) (TType (UVar 24))))
test/quasiquote003/run+1−1
@@ -1,3 +1,3 @@
11#!/usr/bin/env bash
2−idris $@ --check NoInfer.idr
2+idris --consolewidth 80 $@ --check NoInfer.idr
33rm -f *.ibc
test/quasiquote004/expected+2−1
@@ -1,2 +1,3 @@
1−Quasiquote004.idr:50:25:When elaborating right hand side of Quasiquote004.getMeNat':
1+Quasiquote004.idr:50:25:
2+When elaborating right hand side of Quasiquote004.getMeNat':
23Not a Nat goal
test/quasiquote004/run+1−1
@@ -1,3 +1,3 @@
11#!/usr/bin/env bash
2−idris $@ --check --nocolour Quasiquote004.idr
2+idris --consolewidth 80 $@ --check --nocolour Quasiquote004.idr
33rm -f *.ibc
test/reg003/run+2−2
@@ -1,4 +1,4 @@
11#!/usr/bin/env bash
2−idris --check reg003.idr
3−idris --check reg003a.idr
2+idris --consolewidth 80 --check reg003.idr
3+idris --consolewidth 80 --check reg003a.idr
44rm -f *.ibc
test/reg006/expected+2−1
@@ -1 +1,2 @@
1−reg006.idr:17:1:RBTree.lookup is possibly not total due to: RBTree.case block in lookup
1+reg006.idr:17:1:
2+RBTree.lookup is possibly not total due to: RBTree.case block in lookup
test/reg006/run+1−1
@@ -1,3 +1,3 @@
11#!/usr/bin/env bash
2−idris $@ reg006.idr --check
2+idris --consolewidth 80 $@ reg006.idr --check
33rm -f *.ibc
test/reg007/run+1−1
@@ -1,3 +1,3 @@
11#!/usr/bin/env bash
2−idris --nocolour --check $@ reg007.lidr
2+idris --consolewidth 80 --nocolour --check $@ reg007.lidr
33rm -f *.ibc
test/reg010/expected+2−1
@@ -1,2 +1,3 @@
1−reg010.idr:5:15:When elaborating left hand side of with block in usubst.unsafeSubst:
1+reg010.idr:5:15:
2+When elaborating left hand side of with block in usubst.unsafeSubst:
23Can't match on with block in usubst.unsafeSubst warg a P x x px
test/reg010/run+1−1
@@ -1,2 +1,2 @@
11#!/usr/bin/env bash
2−idris $@ reg010.idr --check --nocolour
2+idris --consolewidth 80 $@ reg010.idr --check --nocolour
test/reg018/expected+10−5
@@ -1,5 +1,10 @@
1−reg018a.idr:16:1:conat.minusCoNat is possibly not total due to recursive path conat.minusCoNat
2−reg018a.idr:21:1:conat.loopForever is possibly not total due to: conat.minusCoNat
3−reg018b.idr:8:1:A.showB is possibly not total due to recursive path A.showB
4−reg018c.idr:21:1:CodataTest.inf is possibly not total due to: with block in CodataTest.inf
5−reg018d.idr:8:1:Main.pull is not total as there are missing cases
1+reg018a.idr:16:1:
2+conat.minusCoNat is possibly not total due to recursive path conat.minusCoNat
3+reg018a.idr:21:1:
4+conat.loopForever is possibly not total due to: conat.minusCoNat
5+reg018b.idr:8:1:
6+A.showB is possibly not total due to recursive path A.showB
7+reg018c.idr:21:1:
8+CodataTest.inf is possibly not total due to: with block in CodataTest.inf
9+reg018d.idr:8:1:
10+Main.pull is not total as there are missing cases
test/reg018/run+4−4
@@ -1,6 +1,6 @@
11#!/usr/bin/env bash
2−idris $@ reg018a.idr --check
3−idris $@ reg018b.idr --check
4−idris $@ reg018c.idr --check
5−idris $@ reg018d.idr --check
2+idris --consolewidth 80 $@ reg018a.idr --check
3+idris --consolewidth 80 $@ reg018b.idr --check
4+idris --consolewidth 80 $@ reg018c.idr --check
5+idris --consolewidth 80 $@ reg018d.idr --check
66rm *.ibc
test/reg023/run+1−1
@@ -1,3 +1,3 @@
11#!/usr/bin/env bash
2−idris $@ reg023.idr --check
2+idris --consolewidth 80 $@ reg023.idr --check
33rm -f *.ibc
test/reg027/expected+2−1
@@ -1,3 +1,4 @@
11<<int fn>>
226
3−reg027a.idr:9:10:Overlapping instance: Show (Int -> a) already defined
3+reg027a.idr:9:10:
4+Overlapping instance: Show (Int -> a) already defined
test/reg027/run+2−2
@@ -1,5 +1,5 @@
11#!/usr/bin/env bash
2−idris $@ reg027.idr -o reg027
2+idris --consolewidth 80 $@ reg027.idr -o reg027
33./reg027
4−idris $@ reg027a.idr --check
4+idris --consolewidth 80 $@ reg027a.idr --check
55rm -f reg027 *.ibc
test/reg028/expected+4−2
@@ -1,2 +1,4 @@
1−reg028.idr:5:1:tbad.bad is possibly not total due to: with block in tbad.bad
2−reg028a.idr:11:1:tbad.qsort' is possibly not total due to: with block in tbad.qsort'
1+reg028.idr:5:1:
2+tbad.bad is possibly not total due to: with block in tbad.bad
3+reg028a.idr:11:1:
4+tbad.qsort' is possibly not total due to: with block in tbad.qsort'
test/reg028/run+2−2
@@ -1,4 +1,4 @@
11#!/usr/bin/env bash
2−idris $@ reg028.idr --check
3−idris $@ reg028a.idr --check
2+idris --consolewidth 80 $@ reg028.idr --check
3+idris --consolewidth 80 $@ reg028a.idr --check
44rm -f *.ibc
test/reg034/run+1−1
@@ -1,3 +1,3 @@
11#!/usr/bin/env bash
2−idris --check reg034.idr
2+idris --consolewidth 80 --check reg034.idr
33rm -f reg034 *.ibc
test/reg035/run+3−3
@@ -1,5 +1,5 @@
11#!/usr/bin/env bash
2−idris --check reg035.idr
3−idris --check reg035a.lidr
4−idris --check reg035b.idr
2+idris --consolewidth 80 --check reg035.idr
3+idris --consolewidth 80 --check reg035a.lidr
4+idris --consolewidth 80 --check reg035b.idr
55rm -f *.ibc
test/reg044/run+1−1
@@ -1,3 +1,3 @@
11#!/usr/bin/env bash
2−idris reg044.idr --check
2+idris --consolewidth 80 reg044.idr --check
33rm -f *.ibc
test/reg048/run+1−1
@@ -1,4 +1,4 @@
11#!/usr/bin/env bash
2−idris $@ reg048.idr -o reg048
2+idris $@ reg048.idr -p contrib -o reg048
33./reg048
44rm -f reg048 *.ibc
test/reg049/run+1−1
@@ -1,3 +1,3 @@
11#!/usr/bin/env bash
2−idris --nocolour --check $@ reg049.idr
2+idris --consolewidth 80 --nocolour --check $@ reg049.idr
33rm -f *.ibc
test/reg054/run+1−1
@@ -1,2 +1,2 @@
11#!/usr/bin/env bash
2−idris $@ reg054.idr --check
2+idris --consolewidth 80 $@ reg054.idr --check
test/reg055/run+2−2
@@ -1,5 +1,5 @@
11#!/usr/bin/env bash
2−idris $@ reg055.idr --check
3−idris $@ reg055a.idr --check
2+idris --consolewidth 80 $@ reg055.idr --check
3+idris --consolewidth 80 $@ reg055a.idr --check
44rm -f *.ibc
55
test/reg056/run+1−1
@@ -1,3 +1,3 @@
11#!/usr/bin/env bash
2−idris $@ reg056.idr -o reg056
2+idris --consolewidth 80 $@ reg056.idr -o reg056
33rm -f *.ibc
test/reg060/expectednew file

No changes to the content.

test/reg060/reg060.idrnew file+12
@@ -0,0 +1,12 @@
1+
2+class MyFunctor (f : Type -> Type) where
3+ mymap : (m : a -> b) -> f a -> f b
4+
5+data Foo x y = Bar y
6+
7+instance MyFunctor (Foo m) where
8+ mymap m x = ?wibble
9+
10+instance [foo] Functor m => MyFunctor m where
11+ mymap m x = map m x
12+
test/reg060/runnew file+3
@@ -0,0 +1,3 @@
1+#!/usr/bin/env bash
2+idris $@ reg060.idr --check
3+rm -f *.ibc
test/reg061/Capture.idrnew file+9
@@ -0,0 +1,9 @@
1+module Capture
2+
3+-- Test for variable capture in syntax
4+
5+syntax delay [x] = \z => case z of { () => x }
6+syntax delay' [z] = delay z
7+
8+capture : a -> () -> a
9+capture x = delay' x
test/reg061/expectednew file

No changes to the content.

test/reg061/runnew file+3
@@ -0,0 +1,3 @@
1+#!/usr/bin/env bash
2+idris $@ Capture.idr --check
3+rm -f *.ibc
test/totality001/expected+6−3
@@ -1,3 +1,6 @@
1−test010.idr:15:1:Main.foo is possibly not total due to: Main.MkBad
2−test010a.idr:9:1:main.bar is possibly not total due to: main.MkBad
3−test010b.idr:9:1:main.bar is possibly not total due to: main.MkBad
1+test010.idr:15:1:
2+Main.foo is possibly not total due to: Main.MkBad
3+test010a.idr:9:1:
4+main.bar is possibly not total due to: main.MkBad
5+test010b.idr:9:1:
6+main.bar is possibly not total due to: main.MkBad
test/totality001/run+3−3
@@ -1,6 +1,6 @@
11#!/usr/bin/env bash
2−idris $@ --check test010.idr
3−idris $@ --check test010a.idr
4−idris $@ --check test010b.idr
2+idris --consolewidth 80 $@ --check test010.idr
3+idris --consolewidth 80 $@ --check test010a.idr
4+idris --consolewidth 80 $@ --check test010b.idr
55
66rm -f *.ibc
test/totality002/expected+4−2
@@ -1,2 +1,4 @@
1−test017a.idr:7:1:scg.vtrans is possibly not total due to recursive path scg.vtrans --> scg.vtrans
2−test017b.idr:4:1:foo.foo is possibly not total due to recursive path foo.foo
1+test017a.idr:7:1:
2+scg.vtrans is possibly not total due to recursive path scg.vtrans --> scg.vtrans
3+test017b.idr:4:1:
4+foo.foo is possibly not total due to recursive path foo.foo
test/totality002/run+3−3
@@ -1,5 +1,5 @@
11#!/usr/bin/env bash
2−idris $@ --check test017.idr
3−idris $@ --check test017a.idr
4−idris $@ --check test017b.idr
2+idris --consolewidth 80 $@ --check test017.idr
3+idris --consolewidth 80 $@ --check test017a.idr
4+idris --consolewidth 80 $@ --check test017b.idr
55rm -f *.ibc
test/totality003/expected+2−1
@@ -1 +1,2 @@
1−totality003a.idr:5:1:smaller.qsort is possibly not total due to recursive path smaller.qsort --> smaller.qsort --> smaller.qsort
1+totality003a.idr:5:1:
2+smaller.qsort is possibly not total due to recursive path smaller.qsort --> smaller.qsort --> smaller.qsort
test/totality003/run+2−2
@@ -1,4 +1,4 @@
11#!/usr/bin/env bash
2−idris $@ totality003.idr --check
3−idris $@ totality003a.idr --check
2+idris --consolewidth 80 $@ totality003.idr --check
3+idris --consolewidth 80 $@ totality003a.idr --check
44rm -f *.ibc
test/totality004/expected+4−2
@@ -1,3 +1,5 @@
11[1, 2, 2, 4, 3, 6, 4, 8, 5, 10]
2−totality004a.idr:13:1:Main.process is possibly not total due to recursive path Main.process --> Main.process --> Main.process
3−totality004a.idr:24:1:Main.main is possibly not total due to: Main.process
2+totality004a.idr:13:1:
3+Main.process is possibly not total due to recursive path Main.process --> Main.process --> Main.process
4+totality004a.idr:24:1:
5+Main.main is possibly not total due to: Main.process
test/totality004/run+2−2
@@ -1,5 +1,5 @@
11#!/usr/bin/env bash
2−idris $@ totality004.idr -o totality004
2+idris --consolewidth 80 $@ totality004.idr -o totality004
33./totality004
4−idris $@ --check totality004a.idr
4+idris --consolewidth 80 $@ --check totality004a.idr
55rm -f totality004 *.ibc
test/totality006/expected+4−2
@@ -1,3 +1,5 @@
1−totality006.idr:8:1:Main.prf is not total as there are missing cases
1+totality006.idr:8:1:
2+Main.prf is not total as there are missing cases
23totality006a.idr:11:6:prf' (S _) (S _) Oh is a valid case
3−totality006b.idr:10:1:totality006b.blargh is not total as there are missing cases
4+totality006b.idr:10:1:
5+totality006b.blargh is not total as there are missing cases
test/totality006/run+3−3
@@ -1,5 +1,5 @@
11#!/usr/bin/env bash
2−idris $@ totality006.idr --check
3−idris $@ totality006a.idr --check
4−idris $@ totality006b.idr --check
2+idris --consolewidth 80 $@ totality006.idr --check
3+idris --consolewidth 80 $@ totality006a.idr --check
4+idris --consolewidth 80 $@ totality006b.idr --check
55rm -f *.ibc
test/totality007/expected+2−1
@@ -1,3 +1,4 @@
11Type checking ./Totality.idr
2−Totality.idr:4:1:Totality.foo is not total as there are missing cases
2+Totality.idr:4:1:
3+Totality.foo is not total as there are missing cases
34Totality.idr:4:1:Could not build: Totality.foo is not total as there are missing cases
test/totality007/totality.ipkg+1−1
@@ -2,6 +2,6 @@ package totality
22
33-- totality007
44-- Test that the package builder doesn't allow totality errors in a build
5−opts = ""
5+opts = "--consolewidth 80"
66sourcedir = src
77modules = Totality
test/totality008/expected+2−1
@@ -1 +1,2 @@
1−totality008.idr:7:1:Main.ElimT is possibly not total due to: Main.c2
1+totality008.idr:7:1:
2+Main.ElimT is possibly not total due to: Main.c2
test/totality008/run+1−1
@@ -1,3 +1,3 @@
11#!/usr/bin/env bash
2−idris $@ totality008.idr --check
2+idris --consolewidth 80 $@ totality008.idr --check
33rm -f *.ibc
test/tutorial006/expected+2−1
@@ -10,7 +10,8 @@ When elaborating argument xs to constructor Data.VectType.Vect.::
1010 plus n n
1111 with
1212 plus n m
13−tutorial006b.idr:10:10:When elaborating right hand side of with block in Main.parity:
13+tutorial006b.idr:10:10:
14+When elaborating right hand side of with block in Main.parity:
1415Can't unify
1516 Parity (plus (S j) (S j)) (Type of even)
1617with
test/tutorial006/run+2−2
@@ -1,4 +1,4 @@
11#!/usr/bin/env bash
2−idris $@ tutorial006a.idr --check
3−idris $@ tutorial006b.idr --check
2+idris --consolewidth 80 $@ tutorial006a.idr --check
3+idris --consolewidth 80 $@ tutorial006b.idr --check
44rm -f *.ibc
test/unique001/expected+2−1
@@ -17,4 +17,5 @@ with
1717unique001b.idr:16:7:Borrowed name xs must not be used on RHS
1818unique001c.idr:46:6:Unique name f is used more than once
1919unique001d.idr:3:7:Borrowed name x must not be used on RHS
20−unique001e.idr:3:10:Constructor Main.Nil has a UniqueType, but the data type does not
20+unique001e.idr:3:10:
21+Constructor Main.Nil has a UniqueType, but the data type does not
test/unique001/run+6−6
@@ -1,9 +1,9 @@
11#!/usr/bin/env bash
2−idris $@ unique001.idr -o unique001
2+idris --consolewidth 80 $@ unique001.idr -o unique001
33./unique001
4−idris $@ unique001a.idr --check
5−idris $@ unique001b.idr --check
6−idris $@ unique001c.idr --check
7−idris $@ unique001d.idr --check
8−idris $@ unique001e.idr --check
4+idris --consolewidth 80 $@ unique001a.idr --check
5+idris --consolewidth 80 $@ unique001b.idr --check
6+idris --consolewidth 80 $@ unique001c.idr --check
7+idris --consolewidth 80 $@ unique001d.idr --check
8+idris --consolewidth 80 $@ unique001e.idr --check
99rm -f unique001 *.ibc
test/unique002/run+2−2
@@ -1,4 +1,4 @@
11#!/usr/bin/env bash
2−idris $@ unique002.idr --check
3−idris $@ unique002a.idr --check
2+idris --consolewidth 80 $@ unique002.idr --check
3+idris --consolewidth 80 $@ unique002a.idr --check
44rm -f *.ibc
test/unique003/run+1−1
@@ -1,3 +1,3 @@
11#!/usr/bin/env bash
2−idris $@ unique003.idr --check
2+idris --consolewidth 80 $@ unique003.idr --check
33rm -f *.ibc