Why this OCaml syntax error - syntax-error

I have this code in Ocaml
let double x = 2 * x
let triple x = 3 * x
let s = "Hello" in print_endline s
let () = triple 10 |> string_of_int |> print_endline
and when compiling with ocamlc file.ml this gives the error:
File "file.ml", line 5, characters 16-18:
Error: Syntax error
If I put ;; at the end of line 3 like this
let triple x = 3 * x;;
of if I comment characters 16-18 in line 5 like this
let s = "Hello" (* in print_endline s *)
the syntax error goes away.
Can someone explain the reason of the syntax error, and what each of these two corrections do to resolve it?

let s = "Hello" in print_endline s is not a top level declaration even if it starts with let, it's a let .. in expression. If you don't terminate the preceding expression with ;; it expects what comes next to be part of that expression instead of interpreting it as a top level declaration.
If you remove the in ... part you're changing it from a let ... in expression to a top level let declaration.
You can also turn it into a top level declaration like this:
let () = let s = "Hello" in print_endline s
Edit:
One way of thinking about this is, if instead of having
let triple x = 3 * x
let s = "Hello" in print_endline s
you replace let s = ... in ... with a simpler expression like just "Hello":
let triple x = 3 * x
"Hello"
This is equivalent to
let triple x = 3 * x "Hello"
which will be parsed as applying the argument "Hello" to the function x

Related

Match inside match - ocaml raises syntax error

Does anyone know why this function raises the syntax error? I haven't provided my written side functions, since they are probably not that relevant here, since it's revolving around proper syntax.
I tried deleting the brackets that raised the error (which I think.. should be there?), only to then raise another syntax error one line lower, at the begining of the row with the line "|".
type 'a grid = 'a Array.t Array.t
type problem = { initial_grid : int option grid }
type available = { loc : int * int; possible : int list }
type state = { problem : problem; current_grid : int option grid; available = available list }
let branch_state (state : state) : (state * state) option =
if prazni_kvadratki state.current_grid = [] then
None
else
let lst = prazni_kvadratki state.current_grid in
let loc = List.hd lst in
let st1_grid = copy_grid state.current_grid in
let st2_grid = copy_grid state.current_grid in
match razpolozljive state.current_grid loc with
| x :: xs -> (vstavi_vrednost st1_grid loc (Some x);
let st1 = {problem = state.problem; current_grid = st1_grid} in
match xs with
| [y] -> (vstavi_vrednost st2_grid loc (Some y);
let st2 = {
problem = state.problem;
current_grid = st2_grid
}) (* this is where it shows me a syntax error*)
| y :: ys -> let st2 = {
problem = state.problem;
current_grid = copy_grid state.current_grid;
available = {loc = loc; possible = xs}
})
Some (st1, st2)
On around the 5th last line or so you have let with no matching in. The let expression always must have an in.
The basic rule for nested match is that you should use parentheses or begin/end around the inner one:
match x with
| [] -> 0
| [_] ->
begin
match y with
| [] -> 1
| _ -> 2
end
| _ -> 3
Otherwise the final cases of the outer match look like they belong to the inner one. I don't think this is your problem here because you have no outer cases after the inner match.
Syntax issues
You have a few syntax issues.
type state = { problem : problem; current_grid : int option grid; available = available list }
You likely meant to have:
type state = { problem : problem; current_grid : int option grid; available : available list }
However, given how you construct values later in your program where you provide a value for the available field in one case but not in the other, you may want a variant type that allows your state type to be constructed with or without this value, with distinct behavior when not constructed with this value. This might look like:
type state =
| With_available of { problem : problem;
current_grid : int option grid;
available : available list }
| Without_available of { problem : problem;
current_grid : int option grid }
The other syntax issue is missing an in to go with a let which brings us to:
Scoping issues
There are clearly some miunderstandings here for you in regards to how scope works with let bindings in OCaml.
Aside from a definition at the topmost level of a program, all let bindings are local bindings. That is, they apply to a single expression that trails an in keyword.
Consider this toplevel session.
# let x = 5;;
val x : int = 5
# let y =
let x = 42 in
x + 3;;
val y : int = 45
# x;;
- : int = 5
#
Here the x bound with let x = 42 in x + 3 is only in scope for the duration of the expression x + 3. Once we're done with that expression, that binding for x is gone. In the outer scope, x is still bound to 5.
In both cases in your match you bind names st1 and st2, which would have to be local bindings, but then you try to use them in an outer scope, where they don't exist.
If you want st1 and st2, you'd need to bind them in a similar way to a and b in the below simple example.
# let (a, b) = match [1; 2; 3] with
| [x] -> (x, x)
| x :: y :: _ -> (x, y)
| _ -> (1, 1)
in
a + b;;
- : int = 3
#
Pattern-matching
Please also note that the pattern-matching you're shown is not exhaustive. It does not handle an empty list. If you consider it impossible that an empty list will be a result, you still have to either handle it anyway or use a different data structure than a list which can by definition be empty.
You've shown pattern-matching of the basic pattern:
match some_list with
| x :: xs ->
match xs with
| [y] -> ...
| y :: xs -> ...
We can actually match against the two possibilities you've show in one level of match.
match some_list with
| x :: [y] -> ...
| x :: y :: ys -> ...
If you still need to address y :: ys as xs in the second case, we can readily bind that name with the as keyword.
match some_list with
| x :: [y] -> ...
| x :: (y :: ys as xs) -> ...

Why does the order of operands affect scope?

I'm trying to understand why a certain constructor is accepted in one expression but not another. I would have expected it to be out of scope in both. I'm a rank beginner to OCaml (I mostly use Haskell), so I could be missing something totally obvious to someone experienced.
type zero = Zero
type 'n succ = Succ
type 'n snat =
| SZero : zero snat
| SSucc : 'm snat -> 'm succ snat
module SimpleInduction (Pred : sig type 'n pred end) = struct
open Pred
type hyps =
{ base : zero pred
; step : 'm. 'm pred -> 'm succ pred}
let rec induct : type n. hyps -> n snat -> n pred =
fun h sn -> match sn with
| SZero -> h.base
| SSucc p -> h.step (induct h p)
end;;
let module Snot = struct type 'n pred = Top end in
let module Goop = SimpleInduction(Snot) in
Goop.induct {base = Top; step = fun _ -> Top} SZero = Top;;
(*
let module Snot = struct type 'n pred = Top end in
let module Goop = SimpleInduction(Snot) in
Top = Goop.induct {base = Top; step = fun _ -> Top} SZero;;
*)
This compiles just fine, for some reason. With the second definition of Snot uncommented, I get an error:
19 | Top = Goop.induct {base = Top; step = fun _ -> Top} SZero;;
^^^
Error: Unbound constructor Top
What brings Top into scope in the first definition of Snot? Using regular modules rather than first-classlocal ones makes no difference.
If I use Snot.Top on the left-hand side, I get no complaints on the right-hand side. Why is that?
In short, type-directed disambiguation is indeed not restricted to scope.
With an explicit type annotation, the type checker can select the constructor from the type without bringing the constructor in scope.
For instance,
module M = struct type 'a t = A of 'a end
let ok: _ M.t = A ()
let wrong: _ M.t = A (A ())
the first example is valid because the type annotation is enough to know that the A in A () is an _ A.t. However, the second example does not work because the constructor has not been brought into the scope.
Moreover, type-directed disambiguation only requires the expected type of the constructor or record to be known. Typically, in this example
let expected =
let f (M.A x) = x in
f (A ())
we know that the type of the argument of f is an _ M.t, thus we know that the A in f (A ()) come from _ M.t and we can use type-directed disambiguation like in the case with the explicit annotation.
If you find this behavior exotic, the warning 42 [name-out-of-scope] can be used to warn in such situation. Compiling your example with this warning yields (among many other instances of this warning)
23 | Goop.induct {base = Top; step = fun _ -> Top} SZero = Top
^^^
Warning 40 [name-out-of-scope]: Top was selected from type Snot.pred.
It is not visible in the current scope, and will not
be selected if the type becomes unknown.
(the warning names are new in 4.12)
Concerning your second point, the order of expression may matter in the absence of explicit annotations. Indeed, without explicit annotation, type-directed disambiguation will be only be able to select the right constructor when the expected type is already known. And type checking goes from left to right in OCaml. Thus in
... = Top
the type of the left-hand side has already been inferred and thus the expected type of Top is _ Snot.pred.
When the order is reversed
Top = ...
the typechecker is trying to find a constructor Top without any type information and there are no constructor Top in scope. Thus it fails with an Unbound constructor error. If you want to avoid depending on the order, you can either
write the full name of the constructor:
Snot.Top = ...
use an explicit type annotation
(Top: _ Snot.pred) = ...
open the Snot module.
Snot.( Top ) = ...
(* or *)
let open Snot in Top = ...
I would advise to use one of those solutions since there are more robust.
After all, relying on the specific implementation of the type checking is brittle.
In fact, there is a compiler flag -principal and a warning (18) [not-principal] that takes care to emit a warning in presence of such potentially brittle inference:
23 | Goop.induct {base = Top; step = fun _ -> Top} SZero = Top
^^^
Warning 18 [not-principal]: this type-based constructor disambiguation is not principal.
Here "not principal" means that the result of the type-based disambiguation depended on the order of the type-checking.

Getting syntax error in ocaml

I am trying to make a module that would allow to create a table in ocaml. It would do a query called project to limit the table's values. However on the last line of the definition of the function chooser I am getting syntax error.
module type TABLE =
sig
type database
type table
val create_table: string list * string list* (string list) list -> table
val printTable : table -> string
val listToString : string list -> string
val project : string list * table -> table
val chooser : string list * string list-> string list
end;;
module UsingTable : TABLE =
struct
type table = (string list * string list* (string list) list)
type database = table list
let create_table (a,b,c) = (a,b,c)
let chooser inputList = (
for i = 0 to (List.length trueFalseList-1) do
if List.nth trueFalseList i = "True"
then
(List.nth inputList i)::ans
done
List.rev ans;;)
let project (conditions, aTable)= (
let rec innerProc tmp= function
n,[],v->List.rev tmp
|n,cH::cT,v-> if List.mem cH conditions
then innerProc (["True"]::tmp) (n,cT,v)
else innerProc (["False"]::tmp) (n,cT,v)
in
let trueFalseList = innerProc [] aTable
let rec finalListCreator = match aTable with
n,[],[]->n,[],[]
|n,cH::cT,[]->n,chooser cH ::finalListCreator cT,[]
|n,c,h::t -> n,c,chooser h ::finalListCreator t
)
let rec listToString aList = match aList with
[] -> ""
| h::t -> "\t"^h^"\t"^listToString t
let rec printTable aTable = match aTable with
[],[],[] -> ""
| [],[],vH::vT -> "\n"^(listToString vH)^printTable ([],[],vT)
| [],cH::cT,v -> "\t"^cH^"\t"^printTable([],cT, v)
| n, c , v-> "\n"^(List.hd n)^"\n\n"^printTable([],c, v)
end;;
let atable =UsingTable.create_table (["Student"], ["Id";"Name";"Gender";"Course"],
[["001";"Jim";"M";"AlgoDS"];
["002";"Linnea";"F";"Databases"];
["003";"Anna";"F";"C#"];
["004";"Abby";"F";"C#"];
["005";"Arthur";"M";"JavaScript"]]);;
print_string (UsingTable.printTable atable) ;;
These lines have at least two syntax problems:
let chooser inputList = (
for i = 0 to (List.length trueFalseList-1) do
if List.nth trueFalseList i = "True"
then
(List.nth inputList i)::ans
done
List.rev ans;;)
First, the for .. done is one expression, and List.rev ans is another expression. You need a semicolon (;) between them.
Second, you should use ;; only when you want the input up to that point to be processed. But here if you process the input at the ;; you are missing a right parenthesis.
In my opinion, you should be entering ;; only at the toplevel. The best way to think of this token is as an instruction to the toplevel. It's not part of normal OCaml syntax.
These are only the first two errors. There are quite a few other errors in the code. It might be good to add one function at a time to the module so you can concentrate on a few problems at a time.
Update
The environment you're using is a little bit extra complicated because it has an Evaluate button that asks to evaluate what you've typed so far. This makes the ;; token much less useful.
It would be a good discipline to use this environment without using the ;; token at all. Just click the Evaluate button when you want an evaluation.
The main trick is if you want to evaluate a statement (a unit-valued expression in OCaml) at the outer level, like say Printf.printf "hello world\n". The usual idiom to avoid putting ;; before this is to make it into a declaration like so:
let () = Printf.printf "hello world\n"
That is the one non-obvious idiom that people use when writing source code (where the ;; almost never appears in my experience).

SML converting a string to an int with error catching

So what I want to do is to convert a string into an int and do some error catching on it. I would also like to know where I would put what I want it to do after it fails if it does.
I know how to convert, but I am not sure how to catch it and where the code will jump to after the error
I believe the method for converting it Int.fromString(x)
Thank you.
SML has two approaches to error handling. One, based on raise to raise errors and handle to catch the error, is somewhat similar to how error handling works in languages like Python or Java. It is effective, but the resulting code tends to lose some of its functional flavor. The other method is based on the notion of options. Since the return type of Int.fromString is
string -> int option
it makes the most sense to use the option-based approach.
An int option is either SOME n, where n is and integer, or it is NONE. The function Int.fromString returns the latter if it fails in its attempt to convert the string to an integer. The function which calls Int.fromString can explicitly test for NONE and use the valOf to extract the value in the case that the return value is of the form SOME n. Alternatively, and somewhat more idiomatically, you can use pattern matching in a case expression. Here is a toy example:
fun squareString s =
case Int.fromString(s) of
SOME n => Int.toString (n * n) |
NONE => s ^ " isn't an integer";
This function has type string -> string. Typical output:
- squareString "4";
val it = "16" : string
- squareString "Bob";
val it = "Bob isn't an integer" : string
Note that the clause which starts NONE => is basically an error handler. If the function that you are defining isn't able to handle such errors, it could pass the buck. For example:
fun squareString s =
case Int.fromString(s) of
SOME n => SOME (Int.toString (n * n))|
NONE => NONE;
This has type string -> string option with output now looking like:
- squareString "4";
val it = SOME "16" : string option
- squareString "Bob";
val it = NONE : string option
This would make it the responsibility of the caller to figure out what to do with the option.
The approach to error handling that John explains is elaborated in the StackOverflow question 'Unpacking' the data in an SML DataType without a case statement. The use-case there is a bit different, since it also involves syntax trees, but the same convenience applies for smaller cases:
fun squareString s = Int.fromString s >>= (fn i => SOME (i*i))
Assuming you defined the >>= operator as:
infix 3 >>=
fun NONE >>= _ = NONE
| (SOME a) >>= f = f a
The drawback of using 'a option for error handling is that you have to take into account, every single time you use a function that has this return type, whether it errored. This is not unreasonable. It's like mandatory null-checking. But it comes at the cost of not being able to easily compose your functions (using e.g. the o operator) and a lot of nested case-ofs:
fun inputSqrt s =
case TextIO.inputLine TextIO.stdIn of
NONE => NONE
| SOME s => case Real.fromString s of
NONE => NONE
| SOME x => SOME (Math.sqrt x) handle Domain => NONE
A workaround is that you can build this constant error handling into your function composition operator, as long as all your functions share the same way of expressing errors, e.g. using 'a option:
fun safeSqrt x = SOME (Math.sqrt x) handle Domain => NONE
fun inputSqrt () =
TextIO.inputLine TextIO.stdIn >>=
(fn s => Real.fromString s >>=
(fn x => safeSqrt x))
Or even shorter by applying Eta conversion:
fun inputSqrt () = TextIO.inputLine TextIO.stdIn >>= Real.fromString >>= safeSqrt
This function could fail either because of a lack of input, or because the input didn't convert to a real, or because it was negative. Naturally, this error handling isn't smart enough to say what the error was, so you might want to extend your functions from using an 'a option to using an ('a, 'b) either:
datatype ('a, 'b) either = Left of 'a | Right of 'b
infix 3 >>=
fun (Left msg) >>= _ = Left msg
| (Right a) >>= f = f a
fun try (SOME x) _ = Right x
| try NONE msg = Left msg
fun inputLine () =
try (TextIO.inputLine TextIO.stdIn) "Could not read from stdIn."
fun realFromString s =
try (Real.fromString s) "Could not derive real from string."
fun safeSqrt x =
try (SOME (Math.sqrt x) handle Domain => NONE) "Square root of negative number"
fun inputSqrt () =
inputLine () >>= realFromString >>= safeSqrt
And trying this out:
- ​inputSqrt ();
​9
> val it = Right 3.0 : (string, real) either
- ​inputSqrt ();
​~42
> val it = Left "Square root of negative number" : (string, real) either
- ​inputSqrt ();
Hello
> val it = Left "Could not derive real from string." : (string, real) either
- (TextIO.closeIn TextIO.stdIn; inputSqrt ());
> val it = Left "Could not read from stdIn." : (string, real) either

Generalizing functions in F#

I need a function that produces primes in F#. I found this:
let primesSeq =
let rec nextPrime n p primes =
if primes |> Map.containsKey n then
nextPrime (n + p) p primes
else
primes.Add(n, p)
let rec prime n primes =
seq {
if primes |> Map.containsKey n then
let p = primes.Item n
yield! prime (n + 1) (nextPrime (n + p) p (primes.Remove n))
else
yield n
yield! prime (n + 1) (primes.Add(n * n, n))
}
prime 2 Map.empty
This works very well, but sometimes I need to work with int64/BigInts as well. Is there a more clever way of reusing this code than providing another sequences like these:
let primesSeq64 = Seq.map int64 primesSeq
let primesBigInts = Seq.map (fun (x : int) -> BigInteger(x)) primesSeq
I've heard about modifying a code using "inline" and "LanguagePrimitives", but all I've found was connected with function while my problem is related to a value.
Moreover - I'd like to have a function that works with integer types and computes a floor of a square root.
let inline sqRoot arg = double >> Math.Sqrt >> ... ?
but I can't see a way of returning the same type as "arg" is, as Math.Sqrt returns a double. Again - is there anything better than reimplementing the logic that computes a square root by myself ?
So the general way to do this requires a function and languageprimitives - in your case everywhere you have 1 you write LanguagePrimitives.GenericOne which will produce 1 or 1.0 etc depending on what is required.
To get this to work, you need to create a function value - you can avoid this by doing something like:
let inline primesSeq() = ...
let primesintSeq = primesSeq() //if you use this as an int seq later the compiler will figure it out, otherwise you use
let specified : int seq = primesSeq()
I am not so sure about the sqrt case though - it probably depends on how hacky you are willing to make the solution.
A naïve implementation of generic sqRoot may go along these lines:
let sqRoot arg =
let inline sqrtd a = (double >> sqrt) a
let result = match box(arg) with
| :? int64 as i -> (sqrtd i) |> int64 |> box
| :? int as i -> (sqrtd i) |> int |> box
// cases for other relevant integral types
| _ -> failwith "Unsupported type"
unbox result
and then, checking in FSI:
> let result: int = sqRoot 4;;
val result : int = 2
> let result: int64 = sqRoot 9L;;
val result : int64 = 3L