Why string type is not being accepted if it was expected? - oop

I am trying to create and use a stack object (modified to have strings) from here:
let s = object
val mutable v = [""; ""]
method pop =
match v with
| hd :: tl ->
v <- tl;
Some hd
| [] -> None
method push hd =
v <- hd :: v
end ;;
let () =
s#push "first";
s#push "second";
s#push "third";
print_endline s#pop; (* error from this line *)
print_endline s#pop;
print_endline s#pop;
However, I am getting following error:
$ ocaml objects.ml
File "./objects.ml", line 19, characters 15-20:
Error: This expression has type string option
but an expression was expected of type string
I am not able to understand the error: If the expected type was string why expression of type string is not being accepted?

I am not able to understand the error: If the expected type was string why expression of type string is not being accepted?
Because the expression s#pop doesn't have type string. Its type is string option, i.e., it is either Some s or None, where s has type string.
Look at the pop method implementation, which returns Some s if there are more elements waiting in the stack, or None if the stack is empty,
method pop =
match v with
| hd :: tl ->
v <- tl;
Some hd (* returns `Some hd` *)
| [] -> None (* returns `None` *)
You can implement a helper function, that will print a value of type string option, e.g.,
let print_some s = match s with
| None -> print_endline "empty"
| Some s -> print_endline s
Here is how it is used
let () =
s#push "first";
s#push "second";
s#push "third";
print_some s#pop;
print_some s#pop;
print_some s#pop;
Here are some alternative implementations of the stack object, that use other ways to communicate to the caller that the stack is empty, e.g., a sentinel value from the stack element domain (provided by a user), an exception, or the result type, parametrized with a stringly typed error.
let stack_with_sentinel empty = object
val mutable v = []
method pop = match v with
| hd :: tl ->
v <- tl;
hd
| [] -> empty
end
let stack_with_exception = object
val mutable v = []
method pop = match v with
| hd :: tl ->
v <- tl;
hd
| [] -> raise Not_found
end
let stack_with_result = object
val mutable v = []
method pop = match v with
| hd :: tl ->
v <- tl;
Ok hd
| [] -> Error "empty stack"
end
There are many other ways to define it, but using the option type is the most common.

Related

value level module packing and functors in OCaml

I wonder why one example fails and not the other.
(* this fails *)
(* (l fails to type check)
This expression has type 'a but an expression was expected of type
(module M.TFixU)
The module type M.TFixU would escape its scope
*)
let foldList1 (type ar) algr l =
let module M = FixT (ListIntF) in
let (module LU : M.TFixU) = l in
assert false
(* but this works *)
let foldList2 (type ar) algr l =
let (module LU : FixT(ListIntF).TFixU) = l in
assert false
complete code
module Higher = struct
type ('a, 't) app
module type NewType1 = sig
type 'a s
type t
val inj : 'a s -> ('a, t) app
val prj : ('a, t) app -> 'a s
end
module NewType1 (X : sig
type 'a t
end) =
struct
type 'a s = 'a X.t
type t
external inj : 'a s -> ('a, t) app = "%identity"
external prj : ('a, t) app -> 'a s = "%identity"
end
end
module Fix = struct
open Higher
module FixT (T : NewType1) = struct
module type T_Alg = sig
type a
val alg : (a, T.t) app -> a
end
module type TFixU = sig
module App : functor (A : T_Alg) -> sig
val res : A.a
end
end
type tFixU = (module TFixU)
end
end
module Pb = struct
open Higher
open Fix
(* intro *)
type 'r listIntF = Empty | Succ of (int * 'r)
module ListIntF = NewType1 (struct
type 'r t = 'r listIntF
end)
(* this fails *)
let foldList1 (type ar) algr l =
let module M = FixT (ListIntF) in
let (module LU : M.TFixU) = l in
(* (l fails to type check)
This expression has type 'a but an expression was expected of type
(module M.TFixU)
The module type M.TFixU would escape its scope
*)
let module T = LU.App (struct
type a = ar
let alg = algr
end) in
T.res
(* but this doesn't *)
let foldList2 (type ar) algr l =
let (module LU : FixT(ListIntF).TFixU) = l in
let module T = LU.App (struct
type a = ar
let alg = algr
end) in
T.res
end
In the first case, the type of l is unified with the type defined in the module M, which defines the module type. Since the type is introduced after the value l, which is a parameter in an eager language so it already exists, the value l receives a type that doesn't yet exist at the time of its creation. It is the soundness requirement of the OCaml type system that the value lifetime has to be enclosed with its type lifetime, or more simply each value must have a type. The simplest example is,
let x = ref None (* here `x` doesn't have a type since it is defined later *)
type foo = Foo;; (* the `foo` scope starts here *)
x := Some Foo (* foo escapes the scope as it is assigned to `x` via `foo option` *)
Another simplified example, that involves a function parameter is the following,
let foo x =
let open struct
type foo = Foo
end in
match x with
| Some Foo -> true (* again, type foo escapes the scope as it binds to `x` *)
| None -> false
A very good article that will help you understand in-depth scopes and generalization is Oleg Kiselyov's How OCaml type checker works -- or what polymorphism and garbage collection have in common.
Concerning the second case, you clearly specified the type of l using the applicative nature of OCaml functors. And since the typechecker knows that the lifetime of FixT(ListIntF).TFixU is greater than the lifetime of l it is happy.

OCaml: and keyword syntax error

I've written this mergesort implementation, which works fine if I put the divide function outside of the mergesort function. But when I try to make divide an inner function of mergesort I encounter a syntax error.
I know, there must be some really simple explanation for this. I've looked all over the internet, yet found nothing.
Here is the code:
let mergesort list =
let rec sort lists acc = (
let rec merge sublist1 sublist2 merged_list =
match sublist1 with
|[] -> merged_list # sublist2
|hd1 :: tl1 ->
match sublist2 with
|[] -> merged_list # sublist1
|hd2 :: tl2 ->
if hd1 < hd2 then merge tl1 sublist2 (merged_list # hd1::[])
else merge sublist1 tl2 (merged_list # hd2::[])
in match lists with
|[] ->
(match acc with
|[] -> []
|hd :: [] -> hd
|_ -> sort acc [])
|hd :: tl -> sort (List.tl tl) ((merge (List.hd tl) hd [])::acc)
)
and rec divide list list_of_lists = (
match list with
[] -> list_of_lists
|hd :: tl -> divide tl ((hd :: []) :: list_of_lists)
)
in sort (divide list []) []
;;
and it results into:
Characters 567-570:
and rec divide list list_of_lists = (
^^^
Error: Syntax error
A local definition has the following syntax in OCaml:
let [rec] pattern1 = expr1 and … and patternN = exprN in expr
Thus an extra rec is not allowed after the and keyword, and is allowed only after the first let. The rec flag extends to all values defined in the local definition, thus you just need to remove this erroneous rec after and.
You need to simply remove the rec keyword from your definition there.
This is because when you use the and keyword, you’re effectively repeating the previous definition syntactically, which in this case is let rec.
So your current implementation is effectively the same as saying let rec rec

OCaml syntax error in functor

I'm trying to create a functor that makes a polynomial ring out of a ring. My underlying type, Ring_elt, has the following signature:
module type Ring_elt = sig
type t
val add : t -> t -> t
val mul : t -> t -> t
val zer : t
val one : t
val neg : t -> t
end;;
My polynomial functor looks like:
module Make_Poly2(Underlying:Ring_elt) = struct
type t = Poly of Underlying.t list
let rec create lst =
match List.rev lst with
| Underlying.zer :: tl -> create List.rev tl
| _ -> Poly of lst
end;;
(so the 'create' function should take a list, remove the leading zeros, and then return the polynomial of the result). However, I get a syntax error and utop underlines the "zer" after "Underlying."
By comparison, the following code (for making integer polynomials) works:
module Make_int_poly = struct
type t = Poly of int list
let rec create lst =
match List.rev lst with
| 0 :: tl -> create (List.rev tl)
| _ -> Poly lst
end;;
Any idea what's going on?
An OCaml pattern is built from constants, data constructors, and new names bound by the pattern match. Underlying.zer isn't any of those things. But 0 is one of them.
Seems like you can just use an if to compare against Underlying.zer.
Jeffrey's answer is good but instead of correcting it with an if construction, what you should do is the following : use algebraic data types
Instead of writing
val zer : t
val one : t
You could write
module type Ring_elt = sig
type t = Zer | One | Num of t
val add : t -> t -> t
val mul : t -> t -> t
val neg : t -> t
end
module Make_int_poly = struct
type t = Poly of int list
let rec create lst =
match List.rev lst with
| Underlying.Zer :: tl -> create (List.rev tl)
| _ -> Poly lst
end
It's a much better way of doing it since you can easily pattern match on it and even add some constants to your type t without problems.

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

OCaml - Wrong function type

I have made a class method, and I'd like to have this type :
unit -> (dir -> 'b)
But my actual method:
method iter () = fun x -> match x with
| Up -> if (Stack.is_empty pz) then raise Stack.Empty else if (Stack.length pz = 1) then failwith "Cannot go up" else (ignore (Stack.pop pz) ; {< a = (Stack.top pz) >})
| Down(v) -> match (Stack.top pz) with
| Noeud(o, {contents = []}) -> raise Not_found
| Noeud(o, {contents = l}) -> if mem_assoc v l then ((Stack.push (assoc v l) pz) ; {< a = (Stack.top pz) >} ) else raise Not_found
has the type unit -> dir -> 'b
How can I make it so it becomes the first type?
Here are the custom types :
type 'a arbre = Noeud of 'a option ref * (char * 'a arbre) list ref
type dir = Up | Down of char
Edit: I need this so it can comply to a certain interface, and because of the type mismatch, it won't compile.
Thanks!
This is not the problem. unit -> (dir -> 'b) and unit -> dir -> 'b are the same type in OCaml! (the type arrow is right-associative)
Could you show us the actual error message so we can know where the problem lies?
Addendum: have you actually tried this? If there is no other issue, then you'll find it'll just work.