├── .gitignore ├── CONTRIBUTING.md ├── Koans ├── 01-Arithmetic.idr ├── 02-Equality.idr ├── 03-Boolean.idr ├── 04-Ranges.idr ├── 05-Lists.idr ├── 06-ListComprehensions.idr ├── 07-Tuples.idr ├── 08-HigherOrderFunctions.idr └── Misc.idr ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | \#* 2 | \.#* 3 | 4 | dist 5 | cabal-dev/ 6 | .cabal-sandbox 7 | cabal.sandbox.config 8 | *.ibc 9 | *.o 10 | *.a 11 | *.so 12 | *.dll 13 | *.dylib 14 | *.swp 15 | *~ 16 | .DS_Store 17 | 18 | *.ibc 19 | *~ 20 | dist 21 | cabal-dev 22 | *.o 23 | *.hi 24 | *.chi 25 | *.chs.h 26 | .virthualenv 27 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to 'Idris Koans' 2 | 3 | ## Rules 4 | 5 | * Please aim to make commits self contained. Ideally one thing at a time. 6 | * Commit messages should have a brief (less than 73 characters) leading sentence. Together with a more detailed description where appropriate. 7 | 8 | ## Dev Process 9 | 10 | For developing the project, we aim to follow the following [Git Branching Model](http://nvie.com/posts/a-successful-git-branching-model). 11 | In this model there are two main branches: 12 | 13 | * **master** Reflects the _current_ version of the tutorial inline with the _current_ version of Idris on Hackage. 14 | * **dev** Reflects the latest upstream and current state of the tutorial. 15 | 16 | All pull requests that are for new additions to the project should go to **dev** 17 | All pull requests that detail fixes to the tutorial that is: grammar, spelling, and coding mistakes should be submitted to **master** 18 | 19 | This might sound complicated but in the long term it makes sense in terms of release management. 20 | -------------------------------------------------------------------------------- /Koans/01-Arithmetic.idr: -------------------------------------------------------------------------------- 1 | -- | Some simple arithmetic exercises. 2 | module Koans.Arithmetic 3 | 4 | -- | There were 32 B/W Episodes of Ivor the Engine, and 72 episodes 5 | -- were produced altogether. How many colour episodes were produced? 6 | addition : Bool 7 | addition = ?fillme1 + 32 == 72 8 | 9 | -- | B/W Episodes of Ivor the Engine were ten minutes long. If you 10 | -- were to watch all the episodes in one sitting how many minutes 11 | -- would it take? 12 | multiplication : Bool 13 | multiplication = ?fillme2 == 10 * 32 14 | 15 | -- | In what year did the Colourised version of Ivor the Engine first air? 16 | subtraction : Bool 17 | subtraction = 1977 - ?fillme3 == 3 18 | 19 | -- | 26 B/W episodes of Ivor the Engine were discovered in a Pig shed 20 | -- in 2010. There were two seasons. How many episodes per season were 21 | -- there? 22 | division : Bool 23 | division = 26 / ?fillme4 == 2 24 | 25 | -- | There were 32 B/W episodes of ten minutes each, and 40 colour 26 | -- episodes of five minutes each. How many minutes of Ivor the Engine 27 | -- exist? 28 | parentheses : Int 29 | parentheses = ?fillme5 30 | 31 | -- --------------------------------------------------------------------- [ EOF ] 32 | -------------------------------------------------------------------------------- /Koans/02-Equality.idr: -------------------------------------------------------------------------------- 1 | -- | Exercises on Equality. 2 | module Koans.Equality 3 | 4 | equalityEq : Bool 5 | equalityEq = ?fillme1 == True 6 | 7 | equalityNeq : Bool 8 | equalityNeq = ?fillme2 /= 3 9 | 10 | equalityGeq : Bool 11 | equalityGeq = ?fillme3 >= 4 12 | 13 | equalityGtr : Bool 14 | equalityGtr = ?fillme4 > 4 15 | 16 | equalityLeq : Bool 17 | equalityLeq = ?fillme5 <= 5 18 | 19 | equalityLess : Bool 20 | equalityLess = ?fillme6 < 6 21 | 22 | -- --------------------------------------------------------------------- [ EOF ] 23 | -------------------------------------------------------------------------------- /Koans/03-Boolean.idr: -------------------------------------------------------------------------------- 1 | -- | Exercises on Boolean Relations. 2 | module Koans.Boolean 3 | 4 | logicalAND : Bool 5 | logicalAND = True && ?fillme1 == True 6 | 7 | logicalOR : Bool 8 | logicalOR = False || ?fillme2 == False 9 | 10 | logicalNOT : Bool 11 | logicalNOT = not ?fillme3 == False 12 | 13 | logicalPredicate : Bool 14 | logicalPredicate = not ( ?fillme4 && True) || (?fillme5 && False) == True 15 | 16 | -- --------------------------------------------------------------------- [ EOF ] 17 | -------------------------------------------------------------------------------- /Koans/04-Ranges.idr: -------------------------------------------------------------------------------- 1 | -- | Exercises on Ranges 2 | module Koans.Ranges 3 | 4 | rangeNums : Bool 5 | rangeNums = ?fillme1 == [1..13] 6 | 7 | stepUp : Bool 8 | stepUp = ?fillme2 == [3,6..20] 9 | 10 | stepDown : Bool 11 | stepDown = ?fillme3 == [20,17..1] 12 | 13 | stopMe : List Integer 14 | stopMe = ?fillme4 [1..] 15 | 16 | -- --------------------------------------------------------------------- [ EOF ] 17 | -------------------------------------------------------------------------------- /Koans/05-Lists.idr: -------------------------------------------------------------------------------- 1 | -- | Exercises on Lists 2 | module Koans.Lists 3 | 4 | -- | What is the type of this list. 5 | nats : ?someType 6 | nats = [0,1,2,3,4,5,6,7,9] 7 | 8 | -- | Reproduce the list [0,1,3,5,7,9,2,4,6,8] using the following functions. 9 | odds : List Int 10 | odds = [1,3,5,7,9] 11 | 12 | evens : List Int 13 | evens = [2,4,6,8] 14 | 15 | zero : Int 16 | zero = 0 17 | 18 | zeroOddsEvens : Bool 19 | zeroOddsEvens = ?fillme2 ++ odds ++ ?fillme3 == [0,1,3,5,7,9,2,4,6,8] 20 | 21 | -- | Complete the result of following functions. 22 | 23 | headOList : Bool 24 | headOList = ?fillme4 == Vect.head [5,4,3,2,1] 25 | 26 | tailOList : Bool 27 | tailOList = ?fillme5 == Vect.tail [0,1,2,3,4,5] 28 | 29 | lastOList : Bool 30 | lastOList = ?fillme6 == Vect.last [5,4,3,2,1] 31 | 32 | initOList : Bool 33 | initOList = ?fillme7 == Vect.init [1,2,3,4,5,6] 34 | 35 | lengthOList : Bool 36 | lengthOList = ?fillme8 == List.length [1,2,3,4,5] 37 | 38 | reverseTheList : Bool 39 | reverseTheList = ?fillme9 == List.reverse [1,2,3,4,5] 40 | 41 | first3 : Bool 42 | first3 = ?fillme10 == take 3 [1..10] 43 | 44 | drop3 : Bool 45 | drop3 = ?fillme11 == drop 3 [1..10] 46 | 47 | countAllTheNumbers : Bool 48 | countAllTheNumbers = ?fillme12 == sum [1..10] 49 | 50 | timesAllTheNnumbers : Bool 51 | timesAllTheNnumbers = ?fillme13 == product [1..10] 52 | 53 | elementOrNot : Bool 54 | elementOrNot = List.elem 4 ?fillme14 == True 55 | 56 | -- | Make this function true 57 | stopPete : Bool 58 | stopPete = ?fillme15 (repeat 3) == [3,3,3,3] 59 | 60 | -- --------------------------------------------------------------------- [ EOF ] 61 | -------------------------------------------------------------------------------- /Koans/06-ListComprehensions.idr: -------------------------------------------------------------------------------- 1 | module Koans.ListComprehensions 2 | 3 | -- | What is the result of the List Comprehension. 4 | listCompZero : Bool 5 | listCompZero = ?fillme1 == with Classes [ x + x | x <- [1..5] ] 6 | 7 | -- | Write a list comprehension that returns all the numbers divisible by four, doubled. 8 | myFirstListComp : List Integer -> List Integer 9 | myFirstListComp xs = ?fillme2 10 | 11 | computeList : Bool 12 | computeList = myFirstListComp [1..10] == [8,16] 13 | 14 | -- | Return all the numbers between 20 and 100 that are divisible by 9. 15 | divisibleByNine : List Integer 16 | divisibleByNine = ?fillme3 17 | 18 | -- | Using list comprehensions construct a function that turns a list of numbers into a list of strings. 19 | -- Odd numbers should be bang, Even numbers boom. 20 | boomBangs : List Integer -> List String 21 | boomBangs xs = ?fillme4 22 | where 23 | transform : Integer -> String 24 | transform = ?fillme5 25 | 26 | doBoomBangs : Bool 27 | doBoomBangs = boomBangs [3,4,5,6,7] == ["bang", "boom", "bang", "boom", "bang"] 28 | 29 | 30 | -------------------------------------------------------------------------------- /Koans/07-Tuples.idr: -------------------------------------------------------------------------------- 1 | module Koans.Tuples 2 | 3 | -- Complete the following functions 4 | 5 | firstPair : Bool 6 | firstPair = ?fillme1 == fst ("First", "Pair") 7 | 8 | secondPair : Bool 9 | secondPair = ?fillme2 == snd ("Second", "Pair") 10 | 11 | whatAmI : Vect 5 (Int, Bool) 12 | whatAmI = ?fillme3 13 | 14 | ws : Vect 5 String 15 | ws = ["zip", "a", "dee", "doo", "dah"] 16 | 17 | is : Vect 5 Int 18 | is = ?fillme4 19 | 20 | myFirstZip : Bool 21 | myFirstZip = zip ws is == ?fillme5 22 | 23 | whatIsMyResult : Bool 24 | whatIsMyResult = ?fillme6 == Vect.zipWith (+) is is 25 | -------------------------------------------------------------------------------- /Koans/08-HigherOrderFunctions.idr: -------------------------------------------------------------------------------- 1 | module Koans.HigherOrderFunctions 2 | 3 | -- Complete these functions 4 | 5 | -- Maps are used to map a function to elements in a list. 6 | myFirstMap : Bool 7 | myFirstMap = ?fillme1 == map (2*) [1..4] 8 | 9 | mySecondMap : Bool 10 | mySecondMap = [1, 4, 9, 16, 25] == map ?fillme2 [1..5] 11 | 12 | myThirdMap : Bool 13 | myThirdMap = [25, 16, 9, 4, 1] == map ?fillme3 [1..5] 14 | 15 | -- Folds are used to combine elements in a list from start to finish using a function. 16 | myFirstFold : Bool 17 | myFirstFold = foldl (+) 0 [1..4] == ?fillme4 18 | 19 | mySecondFold : Bool 20 | mySecondFold = 5 == foldl ?fillme5 5 [1..4] 21 | 22 | 23 | -- Scans are like fold but you see the intermediate results, and then the result. 24 | myFirstScan : Bool 25 | myFirstScan = scanl (max) 5 [1,2,3,4] == ?fillme6 26 | 27 | mySecondScan : Bool 28 | mySecondScan = scanl ?fillme7 5 [1,2,10,1] == [5,5,5,10,10] 29 | 30 | myThirdScan : Bool 31 | myThirdScan = scanl (/) 64 [4,2,4] == ?fillme8 32 | 33 | 34 | -- TODO Add examples for scanr and foldr 35 | 36 | 37 | -- You can filter things as well. 38 | 39 | xs : List Int 40 | xs = [1,2,3,4,5,6,7,8,9,10] 41 | 42 | myFirstFilter : Bool 43 | myFirstFilter = filter (>5) xs == ?fillme15 44 | 45 | mySecondFilter : Bool 46 | mySecondFilter = filter ?fillme16 [10,20,30,40,50,60,70,80,90,100] == xs 47 | 48 | -- You can combine functions as well 49 | 50 | myFirstCombi : Bool 51 | myFirstCombi = ["bang", "boom", "bang", "boom", "bang"] == map ?fillme17 (filter ?fillme18 xs) 52 | -------------------------------------------------------------------------------- /Koans/Misc.idr: -------------------------------------------------------------------------------- 1 | module Misc 2 | 3 | smallOdds : List Integer 4 | smallOdds = [x | x <- [1..20], Builtins.mod x 2 == 0 ] 5 | 6 | greeter : String -> String 7 | greeter whom = "Hello to " ++ whom 8 | 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Idris Hackers 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, this 11 | list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | * Neither the name of the {organization} nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | idris-koans 2 | =========== 3 | 4 | Koans are small lessons on the path to enlightenment. 5 | Previously, the _Koans_ method of learning a language has be used by both: [Clojure](http://clojurekoans.com/), [Clojurescript](http://clojurescriptkoans.com/), and [Ruby](http://rubykoans.com/). 6 | With Ruby Koans being the initial Koans project. 7 | The aim of the Idris Koans project is to provide an easy learning environment in which you can learn Idris, and Functional Programming (FP). 8 | Insight will be derived by encountering 'failing' code that requires fixing. 9 | By fixing the code you will learn more about Idris and FP. 10 | 11 | Within the `Koans` folder you will find the various lessons. 12 | Each lesson addresses various topics within FP, and also specific to Idris. 13 | Each lesson consists of a series of functions that when passed through the Idris compiler will either: fail to type check, or have the wrong behaviour. 14 | To pass each lesson each function needs to be completed or fixed so that it type checks, or has deterministic behaviour. 15 | 16 | The files should be attempted in the following order: 17 | 18 | 1. 01-Arithmetic.idr 19 | 1. 02-Equality.idr 20 | 1. 03-Boolean.idr 21 | 1. 04-Ranges.idr 22 | 1. 05-Lists.idr 23 | 1. 06-ListComprehensions.idr 24 | 25 | Idris Koans is in early development and so the list of Koans and method of interaction is primitive. 26 | If you would like to contribute please feel free to do so. 27 | However, please read [CONTRIBUTING.md] first. 28 | We advised the best way to attempt each Koan is to edit the Koan file in your favourite editor, and compile each Koan in the terminal using the Idris compiler. 29 | In future a more interactive environment may be planned. 30 | Either a CLI/REPL environment _a la_ [Clojure Koans](http://clojurekoans.com/), or Web Based _a la_ [Clojurescript Koans](http://clojurescriptkoans.com/) may be added. 31 | 32 | The latest stable release of Idris can easily be installed using cabal: 33 | 34 | $ cabal update; cabal install idris 35 | 36 | Although you can also install Idris from source. 37 | 38 | For editing Idris there is support for both the [Emacs](https://github.com/idris-hackers/idris-mode) and [Vim](https://github.com/idris-hackers/idris-vim) editors. 39 | 40 | More information concerning Idris can be found online from: 41 | 42 | * [idris-lang](http://www.idris-lang.org/) 43 | * [idris-tutorial](https://github.com/idris-hackers/idris-tutorial) 44 | * [idris-hackers](http://idris-hackers.github.io/) 45 | --------------------------------------------------------------------------------