Skip to content

Commit

Permalink
style applied for sml exceptions, errors and refs
Browse files Browse the repository at this point in the history
  • Loading branch information
Whitomtit committed Jun 24, 2024
1 parent 56f3ac8 commit 14c47f4
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 73 deletions.
170 changes: 133 additions & 37 deletions Material/Tutorials/sml/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,25 @@

---

### Case #1

```sml
fun foo x y = x + y;
foo 5 -4;
```
<!-- .element: data-thebe-executable-sml data-language="text/x-ocaml" -->

NOTE: we use `-` and not `~` for negation. actually, ML reads this as `(foo 5) - 4`, so that's why this error is there

<!--vert-->

### Explanation

We use `-` and not `~` for negation. Actually, ML reads this as `(foo 5) - 4`, so that's why this error is there

---

### Case 2

```sml
fun foo x y = x + y;
fun bar (x, y) = x * y;
Expand All @@ -23,20 +31,32 @@ foo 2 bar(1, 2);
```
<!-- .element: data-thebe-executable-sml data-language="text/x-ocaml" -->

NOTE: curried function application is greedy - ML reads this as 3 arguments for `foo`, and you can't pass `bar` as the second argument to `foo` - that's a type error

<!--vert-->

### Explanation

Curried function application is greedy - ML reads this as 3 arguments for `foo`, and you can't pass `bar` as the second argument to `foo` - that's a type error

---

### Case 3

```sml
fun foo [] = 0
| foo x::xs = x;
```
<!-- .element: data-thebe-executable-sml data-language="text/x-ocaml" -->

NOTE: parentheses - needs to be `(x::xs)`. ML considers this to be a triple of `x`, `::`, `xs` and complains about being given a tuple and not a list.

<!--vert-->

### Explanation

Parentheses - needs to be `(x::xs)`. ML considers this to be a triple of `x`, `::`, `xs` and complains about being given a tuple and not a list

---

### Case 4

```sml
case "0" of
"0" => 0
Expand All @@ -46,123 +66,199 @@ case "0" of
```
<!-- .element: data-thebe-executable-sml data-language="text/x-ocaml" -->

NOTE: parentheses - the inner `case` needs to be `(case 0 of _ => 1)`. also notice that the error is a type error, but it's not to be handled as a type error. ML reads the `"2"` and later `_` case as belonging to the second case and not the first one.

<!--vert-->

### Explanation

Parentheses - the inner `case` needs to be `(case 0 of _ => 1)`. Also notice that the error is a type error, but it's not to be handled as a type error. ML reads the `"2"` and later `_` case as belonging to the second case and not the first one

---

### Case 5

```sml
fun foo (a: {x: int, y: int}) = x;
```
<!-- .element: data-thebe-executable-sml data-language="text/x-ocaml" -->

NOTE: `x` is not a field. it's part of the type of `a`. the correct way is `#x a`.

<!--vert-->

### Explanation

`x` is not a field. It's part of the type of `a`. The correct way is `#x a`

---

### Case 6

```sml
type A = {x: int, y: int};
fun foo a = #s1 a;
```
<!-- .element: data-thebe-executable-sml data-language="text/x-ocaml" -->

NOTE: ML cannot do type inferrence to deduce the entire type of `a`, so it results in an error. ML cannot do partial type inferrence.
<!--vert-->

### Explanation

ML cannot do type inferrence to deduce the entire type of `a`, so it results in an error. ML cannot do partial type inferrence

<!--vert-->
---

### Case 7

```sml
Math.pow(2.0, 3.0) - 1;
```
<!-- .element: data-thebe-executable-sml data-language="text/x-ocaml" -->

NOTE: type mismatch. `pow` returns `real`.
<!--vert-->

### Explanation

Type mismatch. `pow` returns `real`

<!--vert-->

### Case 8

```sml
fun f x = Math.sqrt x;
if (f 9.0 = f 9.0) then 1 else 0;
```
<!-- .element: data-thebe-executable-sml data-language="text/x-ocaml" -->

NOTE: `real` is a not a polymorphic equality type - cannot compare `real`s. this is a type error because in ML types that are able to be compared using `=` are denoted by `''a`, and `real` is `'a` but not `''a`.

<!--vert-->

### Explanation

`real` is a not a polymorphic equality type - cannot compare `real`s. This is a type error because in ML types that are able to be compared using `=` are denoted by `''a`, and `real` is `'a` but not `''a`

---

### Case 9

```sml
fun f g x = if g = g then g x else 0;
```
<!-- .element: data-thebe-executable-sml data-language="text/x-ocaml" -->

NOTE: ditto. `g` is a function (actually, `'a -> int`) and functions are not polymorphic equality types. however, since it is first used in a comparison and only then as a function, the error will be reported in the function application and not in the equality. it actually concludes it cannot be a function, rather than concluding it cannot be a polyEqual type.

<!--vert-->

### Explanation

Ditto. `g` is a function (actually, `'a -> int`) and functions are not polymorphic equality types. However, since it is first used in a comparison and only then as a function, the error will be reported in the function application and not in the equality. It actually concludes it cannot be a function, rather than concluding it cannot be a polyEqual type

---

### Case 10

```sml
fun f (a:{s: int, r: int}) = {s: (#s a), r: (#r a)};
```
<!-- .element: data-thebe-executable-sml data-language="text/x-ocaml" -->

NOTE: `:` denotes type, we need to use `=` in the returned expression to denote a value. another common error: `{(#s a), (#r a)}`

<!--vert-->

### Explanation

`:` denotes type, we need to use `=` in the returned expression to denote a value. Another common error: `{(#s a), (#r a)}`

---

### Case 11

```sml
fun f a:{s: int, r: int} = {s = (#s a), r = (#r a)};
```
<!-- .element: data-thebe-executable-sml data-language="text/x-ocaml" -->

NOTE: the type here in the constraint binds to the function - `f`, rather than to `a`, like it may seem. this apparently should not cause an issue, because that is the actual type we are returning, however, it does leave `a` without a precise type constraint and this is a problem because like before, ML cannot do partial type inferrence and it cannot conclude the exact type for `a`, just some of its fields.

<!--vert-->

### Explanation

The type here in the constraint binds to the function - `f`, rather than to `a`, like it may seem. This apparently should not cause an issue, because that is the actual type we are returning, however, it does leave `a` without a precise type constraint and this is a problem because like before, ML cannot do partial type inferrence and it cannot conclude the exact type for `a`, just some of its fields

---

### Case 12

```sml
local
fun rec (a, _, 0) = a | rec (a, b, n) = rec (a+b, a, n-1)
fun rec (a, _, 0) = a
| rec (a, b, n) = rec (a + b, a, n - 1)
in
fun fib n = rec (1, 1, n)
fun fib n = rec (1, 1, n)
end;
```
<!-- .element: data-thebe-executable-sml data-language="text/x-ocaml" -->

NOTE: `rec` is a keyword...

<!--vert-->

### Explanation

`rec` is a keyword...

---

### Case 13

```sml
val x = (1 = 1) and (2 = 2);
```
<!-- .element: data-thebe-executable-sml data-language="text/x-ocaml" -->

NOTE: `andalso` is logical AND and not `and`. also, `orelse` and not `or`

<!--vert-->

### Explanation

`andalso` is logical AND and not `and`. Also, `orelse` and not `or`

---

### Case 14

```sml
val x = "Elad\n";
val x = "Andrey\n";
fun f () = print ("My name is " ^ x);
val x = "Yair\n";
val x = "Maroon\n";
f ();
```
<!-- .element: data-thebe-executable-sml data-language="text/x-ocaml" -->

NOTE: functions freeze the values they refer to, and do not get updated when the identifier is reused.

<!--vert-->

### Explanation

Functions freeze the values they refer to, and do not get updated when the identifier is reused

---

### Case 15

```sml
Math.pow(2.0, 3.0);
floor(it) = 8;
Math.pow (2.0, 3.0);
floor it = 8;
```
<!-- .element: data-thebe-executable-sml data-language="text/x-ocaml" -->

NOTE: this specifically came up in the home ex. terribly annoying floating-point arithmetic error. when doing integer arithmetic, implement manually with a recursive function.

<!--vert-->

### Explanation

This specifically came up in the home ex. Terribly annoying floating-point arithmetic error. When doing integer arithmetic, implement manually with a recursive function.

---

### Case 16

```sml
fun a() = b() and fun b() = a()
fun a () = b () and fun b () = a ()
```
<!-- .element: data-thebe-executable-sml data-language="text/x-ocaml" -->

NOTE: we don't repeat the `fun` keyword after `and`. ditto for `val`, `datatype`.
<!--vert-->

### Explanation

We don't repeat the `fun` keyword after `and`. Ditto for `val`, `datatype`
22 changes: 11 additions & 11 deletions Material/Tutorials/sml/exceptions.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
```sml
datatype int_sol = Success of int | Failure | Impossible;
case methodA(problem) of
case methodA problem of
Success s => Int.toString s
| Failure => (case methodB(problem) of
| Failure => (case methodB problem of
Success s => Int.toString s
| Failure => "Both failed"
| Impossible => "No Good")
Expand Down Expand Up @@ -49,9 +49,9 @@ fun inner = do_calculation
if local_error then raise local_error,
if global_error then raise global_error;
fun middle = inner(…) handle local_error;
fun middle = inner (…) handle local_error;
fun outer = middle(…) handle global_error;
fun outer = middle (…) handle global_error;
```

---
Expand Down Expand Up @@ -134,11 +134,11 @@ local val name = raise Exp in some_declaration end
```sml
exception Empty;
fun hd (x::_) = x
| hd [] = raise Empty;
fun hd (x :: _) = x
| hd [] = raise Empty;
fun tl (_::xs) = xs
| tl [] = raise Empty;
fun tl (_ :: xs) = xs
| tl [] = raise Empty;
```
<!-- .element: data-thebe-executable-sml data-language="text/x-ocaml" -->

Expand Down Expand Up @@ -188,7 +188,7 @@ Exp_0 handle Cons1 x => Exp_1
```sml
fun throw _ = raise Empty;
exception Underflow;
fun bar x = if x>0 then x else raise Underflow;
fun bar x = if x > 0 then x else raise Underflow;
```
<!-- .element: data-thebe-executable-sml data-language="text/x-ocaml" -->

Expand All @@ -197,9 +197,9 @@ fun bar x = if x>0 then x else raise Underflow;
### using exception handling

```sml
case methodA(problem) of
case methodA problem of
Success s => Int.toString s
| Failure => (case methodB(problem) of
| Failure => (case methodB problem of
Success s => Int.toString s
| Failure => "Both failed"
| Impossible => "No Good")
Expand Down
4 changes: 2 additions & 2 deletions Material/Tutorials/sml/lists.md
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ fun map f inpList = foldl
<!-- .element: data-thebe-executable-sml data-language="text/x-ocaml" -->

```sml
map (fn x => x * 2) [1,2,3,4];
map (fn x => x * 2) [1, 2, 3, 4];
```
<!-- .element: data-thebe-executable-sml data-language="text/x-ocaml" -->

Expand Down Expand Up @@ -663,7 +663,7 @@ What will be printed?
```sml
map
(
(fn f => null (f()))
(fn f => null (f ()))
o
(fn t => fn () => tl t)
)
Expand Down
Loading

0 comments on commit 14c47f4

Please sign in to comment.