Skip to content

Commit

Permalink
fix(docs): should fix #399 and unify the markdown syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
EmileRolley committed Aug 20, 2021
1 parent ff9f091 commit 276dac9
Show file tree
Hide file tree
Showing 8 changed files with 267 additions and 210 deletions.
7 changes: 4 additions & 3 deletions docs/tutorials/step-1.md
Expand Up @@ -5,6 +5,7 @@ real effort from the student: any valid OCaml code will be a valid
answer for this exercise.

Let us focus on `test.ml`:

```ocaml
open Test_lib
open Report
Expand Down Expand Up @@ -49,9 +50,9 @@ give 1 point to the student.
directory.
2. Update index.json
3. Build and run the new instance of your local learn-ocaml platform:
```ocaml
learn-ocaml build; learn-ocaml serve
```
```ocaml
learn-ocaml build; learn-ocaml serve
```

At this point, you should see the exercise in the instance opened
on `http://localhost:8080`. Click on grade to get your point!
17 changes: 10 additions & 7 deletions docs/tutorials/step-2.md
Expand Up @@ -2,12 +2,14 @@

Let us now move to the development a basic grader. We ask the student
to implement the identity function and provide the following `template.ml`:

```ocaml
let identity x = "Put your code here"
```

Our goal is to check that this function is modified by the student
in such a way that it behaves as our `solution.ml`:

```ocaml
let identity x = x
```
Expand All @@ -20,6 +22,7 @@ the student gets one point.

Assuming that we choose `int` for this ground type, the behavior described
in the previous paragraph is implemented as follows:

```ocaml
open Test_lib
open Report
Expand Down Expand Up @@ -80,18 +83,20 @@ corresponding report. For a function called `my_function`, it will be


## Want to learn more about grading function ?

The next steps will bring you progressively to understand most of the
possibilities of grading functions. However, if you want to have a better
overview right now, you can go directly to [step
5](step-5.md)
where you will:
* find the signature of `test_function_1_against_solution`
* learn a new grading function for functions
* learn how to change the header report
* have a quick resumé of the utility of each optional arguments with a
- find the signature of `test_function_1_against_solution`
- learn a new grading function for functions
- learn how to change the header report
- have a quick resumé of the utility of each optional arguments with a
link to the right tutorial.

## Multiple arguments

To grade a function with multiple arguments you simply need to use the
corresponding grading function which follows this pattern :
`Test_lib.test_function_<function arity>_against_solution` and give
Expand All @@ -114,12 +119,11 @@ let () =
```


You can find this example in the
`exercises/grade-function-multiple_args` directory (branch: step-2).


## Polymorphic functions : testing several types

For a polymorphic functions, you may want to test the function with
different types. To do so, you can concat the result of numerous grading
functions and encapsulate it in a `Section` which has two arguments :
Expand All @@ -129,7 +133,6 @@ some text and a list of items produced by grading functions.
open Test_lib
open Report
let exercise_1 =
Section ([ Text "Function: "; Code "identity" ; Text " with multiple tested input types." ],
[ test_function_1_against_solution
Expand Down
174 changes: 94 additions & 80 deletions docs/tutorials/step-3.md
@@ -1,6 +1,7 @@
# Step 3: Grading with generators for Ocaml simple built-in types
You can find the examples below in the
`exercises/sampler-built-in-types` directory (branch: step-3).

You can find the examples below in the `exercises/sampler-built-in-types`
directory (branch: step-3).

As see previously, you can either give manually inputs for the tested
functions or you can ask the grader to automatically generate inputs.
Expand All @@ -17,17 +18,26 @@ tuple) for example. Here is a list of the signatures of predefined
samplers :

```ocaml
val sample_int : int sampler
val sample_float : float sampler
val sample_list : ?min_size: int -> ?max_size: int -> ?dups: bool -> ?sorted: bool -> 'a sampler -> 'a list sampler
val sample_array : ?min_size: int -> ?max_size: int -> ?dups: bool -> ?sorted: bool -> 'a sampler -> 'a array sampler
val sample_option : 'a sampler -> 'a option sampler
val sample_string : string sampler
val sample_char : char sampler
val sample_bool : bool sampler
val sample_int : int sampler
val sample_float : float sampler
val sample_list :
?min_size: int ->
?max_size: int ->
?dups: bool ->
?sorted: bool -> 'a sampler -> 'a list sampler
val sample_array :
?min_size: int ->
?max_size: int ->
?dups: bool ->
?sorted: bool -> 'a sampler -> 'a array sampler
val sample_option : 'a sampler -> 'a option sampler
val sample_string : string sampler
val sample_char : char sampler
val sample_bool : bool sampler
```

## How to use a default sampler

When the function to test has inputs of type with predefined sample,
you have nothing to do. In the example below, five tests are
automatically generated.
Expand All @@ -46,14 +56,13 @@ int` to be tested for inputs between 12 and 42, you need to give the
grade function the sampler you want the same way you will to for type
without predefined sampler. There are actually two ways do to that:


## Method 1 : using the `~sampler` argument

The more general way do provide a sampler is to use the optional
argument `~sampler` that has type:

`unit -> <arg1 type> * <arg2 type> * <arg3 type> etc.`.


```ocaml
let exercise_2 =
test_function_2_against_solution
Expand All @@ -64,6 +73,7 @@ let exercise_2 =
```

## Method 2 : redefining the corresponding sampling function.

Another way is to define a sampling function of type `unit -> <arg1
type> * <arg2 type> * <arg3 type> etc.` using the naming convention :
`sample_<type>`. In this case, nothing needs to be add to the grade
Expand All @@ -80,76 +90,80 @@ let exercise_3 =
```

## More avanced examples
You can find the examples below in the
`exercises/advanced-examples-step-3` directory (branch: step-3).

You can find the examples below in the `exercises/advanced-examples-step-3`
directory (branch: step-3).

There is nothing new to learn in this part, there are only more
examples of how to build a sampler for more complexe types. In
particular, there are examples with:

* list
```ocaml
let exercise_1 =
test_function_2_against_solution
[%ty: int -> int list -> int list] "push"
~gen:5
[]
```
* tuple
```ocaml
let exercise_2 =
test_function_1_against_solution
[%ty: (int * int) -> int] "first"
~gen:5
~sampler:(fun () -> (Random.int 10, Random.int 10))
[]
```
* type option
```ocaml
let exercise_3 =
test_function_1_against_solution
[%ty: int option -> int] "opt"
~gen:5
[]
let sampler_4 () =
let sampler_tuple () = (sample_int (), sample_int ()) in
(sample_option sampler_tuple) ()
let exercise_4 =
test_function_1_against_solution
[%ty: (int * int) option -> int] "opt_add"
~gen:5
~sampler:sampler_4
[]
```
* functional type
```ocaml
let sampler_5 () =
let sampler_f () = match Random.int 3 with
| 0 -> succ
| 1 -> pred
| _ -> fun _ -> 0 in
sampler_f (), sample_int ()
let exercise_5 =
test_function_2_against_solution
[%ty: (int -> int) -> int -> int] "apply"
~gen:5
~sampler:sampler_5
[]
```
* array
```ocaml
let sampler_6 =
sample_array ~min_size:1 ~max_size:10 sample_int
let exercise_6 =
test_function_1_against_solution
[%ty: int array -> int list] "array_to_list"
~gen:5
~sampler:sampler_6
[]
```
- list
```ocaml
let exercise_1 =
test_function_2_against_solution
[%ty: int -> int list -> int list] "push"
~gen:5
[]
```

- tuple
```ocaml
let exercise_2 =
test_function_1_against_solution
[%ty: (int * int) -> int] "first"
~gen:5
~sampler:(fun () -> (Random.int 10, Random.int 10))
[]
```

- type option
```ocaml
let exercise_3 =
test_function_1_against_solution
[%ty: int option -> int] "opt"
~gen:5
[]
let sampler_4 () =
let sampler_tuple () = (sample_int (), sample_int ()) in
(sample_option sampler_tuple) ()
let exercise_4 =
test_function_1_against_solution
[%ty: (int * int) option -> int] "opt_add"
~gen:5
~sampler:sampler_4
[]
```

- functional type
```ocaml
let sampler_5 () =
let sampler_f () = match Random.int 3 with
| 0 -> succ
| 1 -> pred
| _ -> fun _ -> 0 in
sampler_f (), sample_int ()
let exercise_5 =
test_function_2_against_solution
[%ty: (int -> int) -> int -> int] "apply"
~gen:5
~sampler:sampler_5
[]
```

- array
```ocaml
let sampler_6 =
sample_array ~min_size:1 ~max_size:10 sample_int
let exercise_6 =
test_function_1_against_solution
[%ty: int array -> int list] "array_to_list"
~gen:5
~sampler:sampler_6
[]
```

0 comments on commit 276dac9

Please sign in to comment.