├── .gitignore ├── 000-start.md ├── 001-hello.dats ├── 002-imports.dats ├── 003-exprs.dats ├── 004-finalization.dats ├── 005-local-bindings.dats ├── 006-tuples.dats ├── 007-records.dats ├── 008-if.dats ├── 009-sequences.dats ├── 010-functions.dats ├── 011-coins.dats ├── 012-tco.dats ├── 013-nqueens.dats ├── 014-mutualrecursive.dats ├── 014-mutualrecursive.md ├── 015-closures.dats ├── 016-higherorder.dats ├── 017-currying.dats ├── 018-datatypes.dats ├── 019-templates.dats ├── 020-polymorphic.dats ├── 021-exceptions.dats ├── 022-io.dats ├── 022-references.dats ├── 023-arrays.dats ├── 023-macros.dats ├── 024-matrices.dats └── 025-dependent-types.dats /.gitignore: -------------------------------------------------------------------------------- 1 | *.c 2 | a.out 3 | -------------------------------------------------------------------------------- /000-start.md: -------------------------------------------------------------------------------- 1 | ## Examples from Introduction to Programming in ATS 2 | 3 | This is my catalogue of all the examples and concepts described in the 4 | book *Introduction to Programming in ATS*. 5 | 6 | ### Motivation 7 | 8 | I'm learning ATS, so I thought I would catalogue my learnings into a 9 | sort of cheatsheet as I go through the book. I and other (potential) 10 | learners can use it as a quick reference. 11 | 12 | The code samples are formatted according to my Haskelly aesthetic. ATS 13 | is notorious for looking very ugly, but I've attempted to make it 14 | pretty. For comparison 15 | [see here](https://gist.github.com/chrisdone/3cbda530e525addb1dc3). 16 | 17 | ### Compiling the examples 18 | 19 | Compile with: 20 | 21 | $ atscc foo.dats 22 | 23 | Run with: 24 | 25 | $ ./a.out 26 | 27 | or: 28 | 29 | $ atscc foo.dats -o foo 30 | 31 | Run with: 32 | 33 | $ ./foo 34 | -------------------------------------------------------------------------------- /001-hello.dats: -------------------------------------------------------------------------------- 1 | (* Simple Hello, World! program. *) 2 | 3 | (* Main entry point. *) 4 | val _ = print "Hello, world!\n" 5 | 6 | implement main () = () 7 | -------------------------------------------------------------------------------- /002-imports.dats: -------------------------------------------------------------------------------- 1 | (* Import some prelude-like functions. *) 2 | 3 | staload _ = "libc/SATS/stdio.sats" 4 | staload _ = "prelude/DATS/array.dats" 5 | staload _ = "prelude/DATS/array0.dats" 6 | staload _ = "prelude/DATS/list.dats" 7 | staload _ = "prelude/DATS/list0.dats" 8 | staload _ = "prelude/DATS/list_vt.dats" 9 | staload _ = "prelude/DATS/matrix.dats" 10 | staload _ = "prelude/DATS/matrix0.dats" 11 | staload _ = "prelude/DATS/option.dats" 12 | staload _ = "prelude/DATS/option0.dats" 13 | staload _ = "prelude/DATS/pointer.dats" 14 | staload _ = "prelude/DATS/reference.dats" 15 | 16 | (* Main entry point. *) 17 | val _ = print "Here is a bunch of useful imports, like a prelude.\n" 18 | 19 | implement main () = () 20 | -------------------------------------------------------------------------------- /003-exprs.dats: -------------------------------------------------------------------------------- 1 | (* Examples of expression types. *) 2 | 3 | (* Integrals are like this. *) 4 | val integral = 1 * 2 5 | 6 | (* Numbers are automatically floating if written like this. *) 7 | val floating = 1.0 / 3 8 | 9 | (* Operator functions can be used prefix like this. *) 10 | val prefixOp = op/(1.0,3) 11 | 12 | (* Characters. *) 13 | val char = 'c' 14 | 15 | (* Negative numbers use a tilde. *) 16 | val negative = ~5 17 | 18 | implement main () = () 19 | -------------------------------------------------------------------------------- /004-finalization.dats: -------------------------------------------------------------------------------- 1 | (* No guarantee of order for finalization for pi and radius. *) 2 | val pi = 3.14 and radius = 10.0 3 | 4 | (* However, area will be finalized after both pi and radius. *) 5 | val area = pi * radius * radius 6 | 7 | (* Just print the area to stdout. *) 8 | val _ = print area 9 | 10 | implement main () = () 11 | -------------------------------------------------------------------------------- /005-local-bindings.dats: -------------------------------------------------------------------------------- 1 | (* Local bindings. *) 2 | 3 | (* You can use ‘let’ syntax to make the ‘area’ binding global, but pi *) 4 | (* and ardius local. *) 5 | val area = 6 | let val pi = 3.14 7 | val radius = 10.0 8 | in pi * radius * radius 9 | end 10 | 11 | (* Alternatively, ‘where’ syntax can be used: *) 12 | val area = 13 | pi * radius * radius 14 | where { 15 | val pi = 3.14 16 | val radius = 10.0 17 | } 18 | 19 | (* Alternatively, to create many top-level bindings with the same *) 20 | (* scope, you can use ‘local’. *) 21 | local 22 | val pi = 3.14 23 | val radius = 10.0 24 | in 25 | val area = pi * radius * radius 26 | end 27 | 28 | (* Use ‘and’ to make bindings share the same environment. *) 29 | val area = 30 | let val pi = 3.14 31 | and radius = 10.0 32 | in pi * radius * radius 33 | end 34 | 35 | (* Main entry point. *) 36 | val _ = print area 37 | 38 | implement main () = () 39 | -------------------------------------------------------------------------------- /006-tuples.dats: -------------------------------------------------------------------------------- 1 | (* Demonstrating tuples. *) 2 | 3 | (* Tuple syntax. *) 4 | val xyz = ('A',1,2.0) 5 | 6 | (* Tuple slots are accessed via their indexes. *) 7 | val x = xyz.0 8 | and y = xyz.1 9 | and z = xyz.2 10 | 11 | val _ = print x 12 | val _ = print "\n" 13 | 14 | val _ = print y 15 | val _ = print "\n" 16 | 17 | val _ = print z 18 | val _ = print "\n" 19 | 20 | (* Pattern matching upon tuples. *) 21 | val (a,b,c) = xyz 22 | 23 | val _ = print a 24 | val _ = print "\n" 25 | 26 | val _ = print b 27 | val _ = print "\n" 28 | 29 | val _ = print c 30 | val _ = print "\n" 31 | 32 | implement main () = () 33 | -------------------------------------------------------------------------------- /007-records.dats: -------------------------------------------------------------------------------- 1 | (* Records. *) 2 | 3 | (* Defines an unboxed record type named ‘point2d’ with fields ‘x’ and ‘y’. *) 4 | typedef Point2D = @{x = double,y = double} 5 | 6 | (* Make a record of type ‘Point2D’: *) 7 | val origin = @{x = 1.0,y = 2.0} : Point2D 8 | 9 | (* Access the fields of the record: *) 10 | val originX = origin.x 11 | and originY = origin.y 12 | 13 | (* Alternatively, pattern matching can be used: *) 14 | val @{x = originX,y = originY} = origin 15 | 16 | (* Wildcards can be used to ignore all fields but a few: *) 17 | val @{x = originX,...} = origin 18 | 19 | implement main () = () 20 | -------------------------------------------------------------------------------- /008-if.dats: -------------------------------------------------------------------------------- 1 | (* If expressions. *) 2 | 3 | (* Some binding to use. *) 4 | val x = 3 5 | 6 | (* If expression can have two branches: *) 7 | val neg = 8 | if x >= 0 9 | then x 10 | else ~x 11 | 12 | implement main () = () 13 | -------------------------------------------------------------------------------- /009-sequences.dats: -------------------------------------------------------------------------------- 1 | (* Sequence expressions. *) 2 | 3 | (* Runs the print commands in sequence. *) 4 | val _ = (print 'H' 5 | ;print 'e' 6 | ;print 'l' 7 | ;print 'l' 8 | ;print 'o') 9 | 10 | (* Alternative form of sequencing. *) 11 | val _ = 12 | begin 13 | print 'H'; 14 | print 'e'; 15 | print 'l'; 16 | print 'l'; 17 | print 'o'; 18 | end 19 | 20 | implement main () = () 21 | -------------------------------------------------------------------------------- /010-functions.dats: -------------------------------------------------------------------------------- 1 | (* Functions. *) 2 | 3 | (* Define a non-recursive symbol x² function. *) 4 | fn square (x : double) : double = 5 | x * x 6 | 7 | (* Anonymous function: *) 8 | val square = 9 | lam (x : double) : double => 10 | x * x 11 | 12 | (* Defines a multi-argument function. *) 13 | fn areaOfRing (R : double, r : double) : double = 14 | 3.1416 * (square R - square r) 15 | 16 | (* Defines a recursive function. *) 17 | fun sum1 (n : int) : int = 18 | if n >= 1 19 | then sum1 (n - 1) + n 20 | else 0 21 | 22 | (* Two-arg recursive function. *) 23 | fun sum2 (m : int, n : int) : int = 24 | if m <= n 25 | then m + sum2 (m + 1, n) 26 | else 0 27 | 28 | (* Cleverer sum. *) 29 | fun sum3 (m : int, n : int) : int = 30 | if m <= n 31 | then let val mn2 = (m + n) / 2 32 | in sum3 (m,mn2 - 1) + mn2 + sum3 (mn2 + 1,n) 33 | end 34 | else 0 35 | 36 | (* Fibonacci. *) 37 | fun fib (n : int) : int = 38 | if n >= 2 39 | then fib (n - 1) + fib (n - 2) 40 | else n 41 | 42 | (* Use the sum1 function: *) 43 | val _ = 44 | begin print (sum1 10); 45 | print "\n"; 46 | end 47 | 48 | (* Use the sum3 function: *) 49 | val _ = 50 | begin print (sum3 (10,100)); 51 | print "\n"; 52 | end 53 | 54 | (* Use the square function: *) 55 | val _ = 56 | begin print (square 5.0); 57 | print "\n"; 58 | end 59 | 60 | (* Use the areaOfRing function: *) 61 | val _ = 62 | begin print (areaOfRing (5.0,2.0)); 63 | print "\n"; 64 | end 65 | 66 | (* Use the fib function: *) 67 | val _ = 68 | print (fib 10) 69 | 70 | implement main () = () 71 | -------------------------------------------------------------------------------- /011-coins.dats: -------------------------------------------------------------------------------- 1 | (* The classic coins denominations problem. *) 2 | 3 | (* Define a 4-tuple of ints. *) 4 | typedef Int4 = (int, int, int, int) 5 | 6 | (* Some example coins. *) 7 | val coins = (1, 5, 10, 25) : Int4 8 | 9 | (* Get coin value by index. *) 10 | fun coinIndex (n : int) : int = 11 | if n = 0 12 | then coins.0 13 | else if n = 1 14 | then coins.1 15 | else if n = 2 16 | then coins.2 17 | else if n = 3 18 | then coins.3 19 | else ~1 20 | 21 | (* Calculate change given by a number. *) 22 | fun coinChange (sum : int) = 23 | go (sum,3) 24 | where { 25 | fun go (sum : int,n : int) : int = 26 | if sum > 0 27 | then if n >= 0 28 | then go (sum,n - 1) + 29 | go (sum - coinIndex (n),n) 30 | else 0 31 | else if sum < 0 32 | then 0 33 | else 1 34 | } 35 | 36 | (* Example usages: *) 37 | val _ = 38 | begin print (coinChange 25); 39 | print "\n"; 40 | print (coinChange 100); 41 | print "\n"; 42 | print (coinChange 0); 43 | print "\n"; 44 | print (coinChange 1); 45 | print "\n"; 46 | end 47 | 48 | implement main () = () 49 | -------------------------------------------------------------------------------- /012-tco.dats: -------------------------------------------------------------------------------- 1 | (* Tail-call optimization. *) 2 | 3 | (* Lispers, MLers and Haskellers will be familiar with this problem. *) 4 | (* You really need this if you want to write efficient loops. *) 5 | 6 | (* Tail recursive sum function. *) 7 | fun sum (n : int,acc : int) : int = 8 | if n > 0 9 | then sum (n - 1,n + acc) 10 | else acc 11 | 12 | (* If you don't want to expose the accumulator argument, 13 | you can use a local function. 14 | *) 15 | fun sum (n : int) : int = 16 | go (n,0) 17 | where { 18 | fun go (n : int,acc : int) : int = 19 | if n > 0 20 | then go (n - 1,n + acc) 21 | else acc 22 | } 23 | 24 | (* Example use: *) 25 | val _ = print (sum 10) 26 | 27 | implement main () = () 28 | -------------------------------------------------------------------------------- /013-nqueens.dats: -------------------------------------------------------------------------------- 1 | (* N-queens problem. *) 2 | 3 | (* Board size. *) 4 | val size : int = 8 5 | 6 | (* Define an 8-tuple of ints. *) 7 | typedef Int8 = (int,int,int,int,int,int,int,int) 8 | 9 | (* Print n dots. *) 10 | fun printDots (i : int) : void = 11 | if i > 0 12 | then begin print ". "; 13 | printDots (i-1); 14 | end 15 | 16 | (* Print a row of the board. *) 17 | fun printRow (i : int) : void = 18 | begin 19 | printDots i; 20 | print "Q "; 21 | printDots (size - i - 1); 22 | print "\n"; 23 | end 24 | 25 | (* Print rows of the board. *) 26 | fun printBoard (bd : Int8) : void = 27 | begin 28 | printRow bd.0; 29 | printRow bd.1; 30 | printRow bd.2; 31 | printRow bd.3; 32 | printRow bd.4; 33 | printRow bd.5; 34 | printRow bd.6; 35 | printRow bd.7; 36 | print "\n"; 37 | end 38 | 39 | (* Get a slot from the board. *) 40 | fun boardIndex (bd : Int8,i : int) : int = 41 | case i of 42 | | 0 => bd.0 43 | | 1 => bd.1 44 | | 2 => bd.2 45 | | 3 => bd.3 46 | | 4 => bd.4 47 | | 5 => bd.5 48 | | 6 => bd.6 49 | | 7 => bd.7 50 | | _ => ~1 51 | 52 | (* Set a value in the board. *) 53 | fun boardSet (bd : Int8,i : int,j:int) : Int8 = 54 | let val (x0,x1,x2,x3,x4,x5,x6,x7) = bd 55 | in case i of 56 | | 0 => (j,x1,x2,x3,x4,x5,x6,x7) 57 | | 1 => (x0,j,x2,x3,x4,x5,x6,x7) 58 | | 2 => (x0,x1,j,x3,x4,x5,x6,x7) 59 | | 3 => (x0,x1,x2,j,x4,x5,x6,x7) 60 | | 4 => (x0,x1,x2,x3,j,x5,x6,x7) 61 | | 5 => (x0,x1,x2,x3,x4,j,x6,x7) 62 | | 6 => (x0,x1,x2,x3,x4,x5,j,x7) 63 | | 7 => (x0,x1,x2,x3,x4,x5,x6,j) 64 | | _ => bd 65 | end 66 | 67 | (* Can a queen piece on row i0 and column j0 capture another one on row i and column j? *) 68 | fun canCapture (i0: int,j0: int,i1: int,j1: int) : bool = 69 | j0 <> j1 andalso 70 | abs (i0 - i1) <> abs (j0 - j1) 71 | 72 | (* Can a queen piece on row i0 and column j0 capture any pieces on 73 | a given board with a row number less than or equal to i? 74 | *) 75 | fun canCaptureLess (i0: int,j0: int,bd: Int8,i: int) : bool = 76 | if i >= 0 77 | then if canCapture (i0,j0,i,boardIndex (bd,i)) 78 | then canCaptureLess (i0,j0,bd,i-1) 79 | else false 80 | else true 81 | 82 | (* Search for and print all solutions. *) 83 | fun search (bd : Int8,i: int,j: int,nsol: int) : int = 84 | if j < size 85 | then 86 | if canCaptureLess (i,j,bd,i-1) 87 | then 88 | let val bd1 = boardSet (bd,i,j) 89 | in if i+1 = size 90 | then begin 91 | print! ("This is solution no. ",nsol + 1,":\n\n"); 92 | printBoard bd1; 93 | search (bd,i,j + 1,nsol + 1); 94 | end 95 | else search (bd1,i + 1,0,nsol) 96 | end 97 | else search (bd,i,j + 1,nsol) 98 | else if i > 0 99 | then search (bd,i - 1,boardIndex (bd,i - 1) + 1,nsol) 100 | else nsol 101 | 102 | (* Print a sample board. *) 103 | val _ = printBoard @(0,1,2,3,4,5,6,7) 104 | 105 | (* Print out solutions. *) 106 | val _ = search (@(0,0,0,0,0,0,0,0),0,1,0) 107 | 108 | implement main () = () 109 | -------------------------------------------------------------------------------- /014-mutualrecursive.dats: -------------------------------------------------------------------------------- 1 | (* Mutually recursive functions. *) 2 | 3 | (* Use the fn* function, sort of wildcard : combine all the functions 4 | into one and uses local jumps for calling eachother. 5 | *) 6 | fn* isevn (n : int) : bool = 7 | if n > 0 8 | then isodd (n - 1) 9 | else true 10 | and isodd (n : int) : bool = 11 | if n > 0 12 | then isevn (n - 1) 13 | else false 14 | 15 | (* Print out a standard multiplication table for nonzero digits. *) 16 | fun print_multable () = 17 | go1 1 18 | where { 19 | fn* go1 (i : int) : void = 20 | if i <= 9 21 | then go2 (i,1) 22 | else () 23 | and go2 (i : int,j : int) : void = 24 | if j <= i 25 | then begin if j >= 2 then print " "; 26 | printf ("%dx%d=%2.2d",@(j,i,j * i)); 27 | go2 (i,j + 1) 28 | end 29 | else begin print_newline (); 30 | go1 (i + 1) 31 | end 32 | } 33 | 34 | val _ = print_multable () 35 | 36 | implement main () = () 37 | -------------------------------------------------------------------------------- /014-mutualrecursive.md: -------------------------------------------------------------------------------- 1 | Prints out: 2 | 3 | 1x1=01 4 | 1x2=02 2x2=04 5 | 1x3=03 2x3=06 3x3=09 6 | 1x4=04 2x4=08 3x4=12 4x4=16 7 | 1x5=05 2x5=10 3x5=15 4x5=20 5x5=25 8 | 1x6=06 2x6=12 3x6=18 4x6=24 5x6=30 6x6=36 9 | 1x7=07 2x7=14 3x7=21 4x7=28 5x7=35 6x7=42 7x7=49 10 | 1x8=08 2x8=16 3x8=24 4x8=32 5x8=40 6x8=48 7x8=56 8x8=64 11 | 1x9=09 2x9=18 3x9=27 4x9=36 5x9=45 6x9=54 7x9=63 8x9=72 9x9=81 12 | -------------------------------------------------------------------------------- /015-closures.dats: -------------------------------------------------------------------------------- 1 | (* Closures 2 | 3 | Functions in ATS, like C, do not carry environments for 4 | closures. Use : to enable this. 5 | 6 | *) 7 | 8 | (* Use the cloref1 type to indicate that `loop` closes over `n'. 9 | Note that there is no space between : and . 10 | *) 11 | fun sum (n : int) : int = 12 | let fun loop (i : int, res : int) : int = 13 | if i <= n 14 | then loop (i + 1,res + i) 15 | else res 16 | in loop (1,0) 17 | end 18 | 19 | (* Making anonymous closing functions. *) 20 | fun addx (x : int) : int - int = 21 | lam y => x + y 22 | 23 | (* plus1 has type int - int *) 24 | val plus1 = addx (1) 25 | 26 | (* plus2 has type int - int *) 27 | val plus2 = addx (2) 28 | 29 | (* Demonstrate closure calls. *) 30 | val _ = 31 | begin print! (sum 10,"\n"); 32 | print! (plus1 10,"\n"); 33 | print! (plus2 10,"\n"); 34 | end 35 | 36 | implement main () = () 37 | -------------------------------------------------------------------------------- /016-higherorder.dats: -------------------------------------------------------------------------------- 1 | (* Higher-order functions *) 2 | 3 | (* Given a function from integers to integers, rtfind searches for the 4 | first natural number that is a root of the function. For instance, 5 | calling rtfind on the polynomial function lam x => x * x - x + 110 6 | returns 11. Note that rtfind loops forever if it is applied to a 7 | function that does not have a root. 8 | *) 9 | fun rtfind (f : int -> int) : int = 10 | loop (f,0) 11 | where { 12 | fun loop (f : int -> int,n : int) : int = 13 | if f (n) = 0 14 | then n 15 | else loop (f,n + 1) 16 | } 17 | 18 | (* An integer fold. *) 19 | fun ifold (n : int,f : (int,int) -> int,ini : int) : int = 20 | if n > 0 21 | then f (ifold (n - 1,f,ini),n) 22 | else ini 23 | 24 | (* Sum implemented in terms of ifold. *) 25 | fun sum (n : int) : int = 26 | ifold (n,lam (res,x) => res + x,0) 27 | 28 | (* Prod implemented in terms of ifold. *) 29 | fun prod (n : int) : int = 30 | ifold (n,lam (res,x) => res * x,1) 31 | 32 | (* Compute the sum of the squares of the integers ranging from 1 to a 33 | given natural number. *) 34 | fun sqrsum (n : int) : int = 35 | ifold (n,lam (res,x) => res + x * x,0) 36 | 37 | (* Demos of functions defined in terms of higher-order functions. *) 38 | val _ = 39 | begin print! (sqrsum 6,"\n"); 40 | print! (prod 5,"\n"); 41 | print! (sum 10,"\n"); 42 | end 43 | 44 | implement main () = () 45 | -------------------------------------------------------------------------------- /017-currying.dats: -------------------------------------------------------------------------------- 1 | (* Currying *) 2 | 3 | (* Uncurried Ackermann. *) 4 | fun acker1 (m: int, n: int): int = 5 | if m > 0 then 6 | if n > 0 then acker1 (m-1, acker1 (m, n-1)) else acker1 (m-1, 1) 7 | else n+1 8 | 9 | (* Curried Ackermann. *) 10 | fun acker2 (m: int) (n: int): int = 11 | if m > 0 then 12 | if n > 0 then acker2 (m-1) (acker2 m (n-1)) else acker2 (m-1) 1 13 | else n+1 14 | 15 | (* Demo of uncurried vs curried args. *) 16 | val _ = 17 | begin print! (acker1 (2,2),"\n"); 18 | print! (acker2 2 2,"\n"); 19 | end 20 | 21 | implement main () = () 22 | -------------------------------------------------------------------------------- /018-datatypes.dats: -------------------------------------------------------------------------------- 1 | (* Data types *) 2 | 3 | (* A type like Maybe or Option *) 4 | datatype MaybeInt = 5 | | NothingInt of () 6 | | JustInt of int 7 | 8 | (* Day of the week. *) 9 | datatype Day = 10 | | Monday of () 11 | | Tuesday of () 12 | | Wednesday of () 13 | | Thursday of () 14 | | Friday of () 15 | | Saturday of () 16 | | Sunday of () 17 | 18 | (* Char list *) 19 | datatype ListChar = 20 | | NilChar of () | ConsChar of (char, ListChar) 21 | 22 | (* Example of list of chars. *) 23 | val exampleChars = 24 | ConsChar ('a',ConsChar ('b',ConsChar ('c',NilChar ()))) 25 | 26 | (* Get length of a list of chars. *) 27 | fun charsLength (cs : ListChar) : int = 28 | case cs of 29 | | ConsChar (_,cs) => 1 + charsLength (cs) 30 | | NilChar () => 0 31 | 32 | (* Tail-recursive version of charsLength. *) 33 | fun charsLengthTCO (cs : ListChar) : int = 34 | go (cs,0) 35 | where { 36 | fun go (cs : ListChar,n : int) : int = 37 | case cs of 38 | | ConsChar (_,cs) => go (cs,n + 1) 39 | | NilChar () => n 40 | } 41 | (* Is the given day a weekday? *) 42 | fun isWeekday (x : Day) : bool = 43 | case x of 44 | | Saturday () => false 45 | | Sunday () => false 46 | | _ => true 47 | 48 | (* Demo of types. *) 49 | val mint = JustInt 10 50 | val day = 51 | case mint of 52 | | JustInt 0 => Thursday () 53 | | JustInt i => Wednesday () 54 | | _ => Friday () 55 | val _ = 56 | begin print! (case mint of 57 | | JustInt 0 => ~1 58 | | JustInt i => i 59 | | _ => 0 60 | ,"\n"); 61 | case () of 62 | () => print! ("Unit is unit!","\n"); 63 | print! (isWeekday day,"\n"); 64 | print (isWeekday (Saturday ())) 65 | end 66 | 67 | implement main () = () 68 | -------------------------------------------------------------------------------- /019-templates.dats: -------------------------------------------------------------------------------- 1 | (* Function templates *) 2 | 3 | (* This function is polymorphic over the two types of the tuple. *) 4 | fun {a,b : t@ype} swap ((x,y) : (a,b)) = (y,x) 5 | (* ^ That is the "sort" (in Haskell: kind, in Idris: type) of 6 | the types a and b. I have no idea why such an ugly name 7 | as "t@ype" was chosen. 8 | *) 9 | 10 | (* Basic tuple. *) 11 | val ab = (10,"foo") 12 | 13 | (* Swapped tuple. *) 14 | val ba = swap ab 15 | 16 | (* Compose two functions. *) 17 | typedef Compose (f : t@ype, g : t@ype) = 18 | f - g 19 | (* ^ Yep, that's also real. *) 20 | 21 | (* Identity on boxed types. *) 22 | fun {a : type} identB (x : a) : a = x 23 | 24 | (* Identity on unboxed types. *) 25 | fun {a : t@ype} identU (x : a) : a = x 26 | 27 | val _ = identU (123 : int) 28 | 29 | (* In Haskell this type is like: 30 | 31 | (.) :: (b -> c) -> (a -> b) -> (a -> c) 32 | 33 | *) 34 | fun {a,b,c : t@ype} compose (f : Compose (b,c),g : Compose (a,b)) : Compose (a,c) = 35 | lam x => f (g x) 36 | 37 | (* Simple function to be used in composition. *) 38 | val plus1 = lam (x : int) : int = 39 | x + 1 40 | 41 | (* Simple function to be used in composition. *) 42 | val times2 = lam (x : int) : int = 43 | x * 2 44 | 45 | (* Composition of two functions. *) 46 | val plus1ThenTimes2: Compose (int,int) = 47 | compose (times2,plus1) 48 | 49 | (* Composition of two functions: visa-versa *) 50 | (* Alternate way of writing. *) 51 | val times2ThenPlus1: int - int = 52 | compose (plus1,times2) 53 | 54 | (* Demo of templates. *) 55 | val _ = 56 | begin 57 | print! (ab.0,",",ab.1,"\n"); 58 | print! (ba.0,",",ba.1,"\n"); 59 | print! (times2ThenPlus1 5); 60 | end 61 | 62 | implement main () = () 63 | -------------------------------------------------------------------------------- /020-polymorphic.dats: -------------------------------------------------------------------------------- 1 | (* Polymorphic functions *) 2 | 3 | (* Swapping of boxed tuples. *) 4 | fun swapBoxed {a,b : type} ((x,y) : (a,b)) : (b,a) = 5 | (y,x) 6 | 7 | fun swapUnoxed {a,b : t@ype} ((x,y) : (a,b)) : (b,a) = 8 | (y,x) 9 | 10 | (* List data type. *) 11 | datatype List (a : type) = 12 | | Nil (a) of () 13 | | Cons (a) of (a,List a) 14 | 15 | (* Option type. *) 16 | datatype Option (a : type) = 17 | | None (a) of () 18 | | Someome (a) of a 19 | 20 | (* Length *) 21 | fun {a : type} listLength (xs : List a) : int = 22 | case xs of 23 | | Cons (_,xs) => 1 + listLength xs 24 | | Nil () => 0 25 | 26 | (* Sample tuple. *) 27 | val AB = ("A","B") 28 | 29 | (* The {string,string} arguments isn't necessary, but sometimes it is. *) 30 | val BA1 = swapBoxed {string,string} AB 31 | val BA2 = swapBoxed AB 32 | 33 | implement main () = () 34 | -------------------------------------------------------------------------------- /021-exceptions.dats: -------------------------------------------------------------------------------- 1 | (* Exceptions *) 2 | 3 | (* List data type. *) 4 | datatype List (a : t@ype) = 5 | | Nil (a) of () 6 | | Cons (a) of (a,List a) 7 | 8 | (* Product of a list of ints. *) 9 | fun listProd (xs : List int) : int = 10 | (try go (xs) 11 | with ~DivisionByZero () => 0) 12 | where { 13 | exception DivisionByZero of () 14 | fun go (xs : List int) : int = 15 | case xs of 16 | | Cons (x,xs) => 17 | if x = 0 18 | then $raise DivisionByZero() 19 | else x * go (xs) 20 | | Nil => 1 21 | } 22 | 23 | (* Demo of exception handling *) 24 | val _ = 25 | begin print! (listProd(Cons (1,Cons (2,Nil ()))),"\n"); 26 | end 27 | 28 | implement main () = () 29 | -------------------------------------------------------------------------------- /022-io.dats: -------------------------------------------------------------------------------- 1 | (* I/O *) 2 | 3 | staload _(*anon*) = "libc/SATS/stdio.sats" 4 | 5 | (* Open a file *) 6 | val out = open_file_exn ("hello.txt",file_mode_w) 7 | 8 | (* Do some actions with the file *) 9 | val _ = 10 | begin fprint_string (out,"Hello,world!\n"); 11 | close_file_exn (out); 12 | end 13 | 14 | (* A simple get line / output line loop. *) 15 | fun loop (): void = 16 | let val line = input_line (stdin_ref) 17 | in if stropt_is_some (line) 18 | then begin output_line (stdout_ref,stropt_unsome (line)); 19 | loop (); 20 | end 21 | else () 22 | end 23 | 24 | val _ = loop () 25 | 26 | implement main () = () 27 | -------------------------------------------------------------------------------- /022-references.dats: -------------------------------------------------------------------------------- 1 | (* References *) 2 | 3 | (* Import references lib. *) 4 | staload _(*anon*) = "prelude/DATS/reference.dats" 5 | 6 | (* Create a ref and initialize it with 0. *) 7 | val intr = ref (0) 8 | 9 | (* Increment the reference. *) 10 | val () = !intr := !intr + 1 11 | val i = !intr 12 | 13 | (* A simple mutable counter. *) 14 | typedef Counter = 15 | '{ get = () - int 16 | , inc = () - void 17 | , reset = () - void 18 | } 19 | 20 | (* Make a new counter. *) 21 | fun newCounter () : Counter = 22 | let val count = ref (0) 23 | in '{get = lam () => !count 24 | ,inc = lam () => !count := !count + 1 25 | ,reset = lam () => !count := 0 26 | } 27 | end 28 | 29 | (* Demo of *) 30 | val _ = 31 | begin print! (i,"\n"); 32 | end 33 | 34 | implement main () = () 35 | -------------------------------------------------------------------------------- /023-arrays.dats: -------------------------------------------------------------------------------- 1 | (* Arrays *) 2 | 3 | staload _(*anon*) = "prelude/DATS/array.dats" 4 | staload _(*anon*) = "prelude/DATS/array0.dats" 5 | 6 | (* Insertion sort. *) 7 | fun {a : t@ype} insertionSort (array : array0 (a),cmp : (a,a) -> int) : void = 8 | go 1 9 | where { 10 | val arraySize = array0_size array 11 | val length = int_of_size arraySize 12 | fun ins (x : a,i : int) : void = 13 | if i >= 0 14 | then 15 | if cmp (x,array[i]) < 0 16 | then begin array[i+ 1] := array[i]; 17 | ins (x,i - 1); 18 | end 19 | else array[i+1] := x 20 | else array[0] := x 21 | fun go (i : int) : void = 22 | if i < length 23 | then begin ins (array[i],i - 1); 24 | go (i + 1); 25 | end 26 | else () 27 | } 28 | 29 | implement main () = () 30 | -------------------------------------------------------------------------------- /023-macros.dats: -------------------------------------------------------------------------------- 1 | (* Macros *) 2 | 3 | (* A macro to compute cubes. *) 4 | macrodef cube (x) = 5 | `(,(x) * ,(x) * ,(x)) 6 | 7 | (* Example of using cube. *) 8 | fun cubesum (i : int,j : int) : int = 9 | ,(cube `(i)) + ,(cube `(j)) 10 | 11 | implement main () = () 12 | -------------------------------------------------------------------------------- /024-matrices.dats: -------------------------------------------------------------------------------- 1 | (* Matrices *) 2 | 3 | (* Transpose a matrix. *) 4 | fun {a : t@ype} transpose (matrix : matrix0 a) : void = 5 | goRows 0 6 | where { 7 | val nrow = matrix0_row (matrix) 8 | fn* goRows (i : size_t) : void = 9 | if i < nrow 10 | then goCols (i,0) 11 | else () 12 | and goCols (i : size_t,j : size_t) : void = 13 | if j < i 14 | then let val tmp = matrix[i,j] 15 | in begin matrix[i,j] := matrix[j,i]; 16 | matrix[j,i] := tmp; 17 | goCols (i,j + 1) 18 | end 19 | end 20 | else goRows (i + 1) 21 | } 22 | 23 | implement main () = () 24 | -------------------------------------------------------------------------------- /025-dependent-types.dats: -------------------------------------------------------------------------------- 1 | (* Dependent types *) 2 | 3 | (* Define a sort. *) 4 | sortdef nat = {a: int | a >= 0} 5 | 6 | (* Define a natural type. It's existential constrained upon the sort `nat'. *) 7 | typedef Nat = [a:nat] int (a) 8 | 9 | (* A valid natural number. *) 10 | val _ = 2 : Nat 11 | 12 | (* The following does not compile: *) 13 | (* val _ = 5-2 : Nat *) 14 | 15 | (* Successor that only accepts integers i>=0 and must return i+1. *) 16 | fun {i : int | i >= 0} succ (i : int i) : int (i + 1) = 17 | i + 1 18 | 19 | (* Use of succ. *) 20 | val _ = succ (5-2) 21 | 22 | implement main () = () 23 | --------------------------------------------------------------------------------