SML converting a string to an int with error catching - error-handling

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

Related

Error when trying to convert a list of objects in a string using reduce function

I am playing with kotlin language and I tried the following code:
data class D( val n: Int, val s: String )
val lst = listOf( D(1,"one"), D(2, "two" ) )
val res = lst.reduce { acc:String, d:D -> acc + ", " + d.toString() }
The last statement causes the following errors:
Expected parameter of type String
Expected parameter of type String
Type mismatch: inferred type is D but String was expected
while this version of the last statement works:
val res = lst.map { e -> e.toString() }.reduce { acc, el -> acc + ", " + el }
I do not understand why the first version does not work. The formal definition of the reduce function, found here, is the following:
inline fun <S, T : S> Iterable<T>.reduce(
operation: (acc: S, T) -> S
): S
But this seems in contrast with the following sentence, on the same page:
Accumulates value starting with the first element and applying
operation from left to right to current accumulator value and each
element.
That is, as explained here:
The difference between the two functions is that fold() takes an
initial value and uses it as the accumulated value on the first step,
whereas the first step of reduce() uses the first and the second
elements as operation arguments on the first step.
But, to be able to apply the operation on first and second element, and so on, it seems to me tha the operation shall have both arguments of the base type of the Iterable.
So, what am I missing ?
Reduce is not the right tool here. The best function in this case is joinToString:
listOf(D(1, "one"), D(2, "two"))
.joinToString(", ")
.let { println(it) }
This prints:
D(n=1, s=one), D(n=2, s=two)
reduce is not designed for converting types, it's designed for reducing a collection of elements to a single element of the same type. You don't want to reduce to a single D, you want a string. You could try implementing it with fold, which is like reduce but takes an initial element you want to fold into:
listOf(D(1, "one"), D(2, "two"))
.fold("") { acc, d -> "$acc, $d" }
.let { println(it) }
However, this will add an extra comma:
, D(n=1, s=one), D(n=2, s=two)
Which is exactly why joinToString exists.
You can see the definition to understand why its not working
To make it work, you can simply create an extension function:
fun List<D>.reduce(operation: (acc: String, D) -> String): String {
if (isEmpty())
throw UnsupportedOperationException("Empty list can't be reduced.")
var accumulator = this[0].toString()
for (index in 1..lastIndex) {
accumulator = operation(accumulator, this[index])
}
return accumulator
}
you can use it as:
val res = lst.reduce { acc:String, d:D -> acc + ", " + d.toString() }
or simply:
val res = lst.reduce { acc, d -> "$acc, $d" }
You can modify the function to be more generic if you want to.
TL;DR
Your code acc:String is already a false statement inside this line:
val res = lst.reduce { acc:String, d:D -> acc + ", " + d.toString() }
Because acc can only be D, never a String! Reduce returns the same type as the Iterable it is performed on and lst is Iterable<D>.
Explanation
You already looked up the definition of reduce
inline fun <S, T : S> Iterable<T>.reduce(
operation: (acc: S, T) -> S
): S
so lets try to put your code inside:
lst is of type List<D>
since List extends Iterable, we can write lst : Iterable<D>
reduce will look like this now:
inline fun <D, T : D> Iterable<T>.reduce(
operation: (acc: D, T) -> D //String is literally impossible here, because D is not a String
): S
and written out:
lst<D>.reduce { acc:D, d:D -> }

Does the Kotlin Fold Function require type casting or specifying lambda type?

I am looking at the documentation for the Kotlin fold function and am having a bit of difficulty understanding what is going on. The example they provide is as follows:
val fruits = listOf("apple", "apricot", "banana", "blueberry", "cherry", "coconut")
// collect only even length Strings
val evenFruits = fruits.groupingBy { it.first() }
.fold(listOf<String>()) { acc, e -> if (e.length % 2 == 0) acc + e else acc }
println(evenFruits) // {a=[], b=[banana], c=[cherry]}
They say there should only be a single "operation function" as an argument.
.fold(listOf<String>()) { acc, e -> if (e.length % 2 == 0) acc + e else acc }
However, in addition to the lambda, they also have the (listOf<String>()) part. While the lack of parentheses around arguments on some function calls confuses me sometimes, I imagine this can't possibly be a function call all on its own. Does the Kotlin fold Function require typecasting or specifying lambda type? If I get rid of that code snippet it breaks. I was pretty sure that the only way to specify a type was anonymous functions with a return type and not lambdas so I'm really not too sure what is going on here. I am new to Kotlin so any explanations as to what this syntax means and how the fold function works would be appreciated.
Here is the link to the documentation: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/fold.html
In the linked documentation you can see there are 2 arguments:
inline fun <T, R> Iterable<T>.fold(
initial: R,
operation: (acc: R, T) -> R
): R
By the trailing lambda rule, the call is another way to write
.fold(listOf<String>(), { acc, e -> if (e.length % 2 == 0) acc + e else acc })
So initial is listOf<String>() and operation is { acc, e -> if (e.length % 2 == 0) acc + e else acc }. The reason String needs to be specified in listOf<String>() is that it helps the compiler figure out that R is List<String> and then it knows the types of both arguments in { acc, e -> ... }.
If I get rid of that code snippet it breaks.
If you mean just removing (listOf<String>()) then you are left with one argument, and fold requires two.
Does the Kotlin fold Function require typecasting or specifying lambda type?
Well, there is no typecasting or specifying lambda type in the example, so it doesn't.

The signature for this packaged module couldn't be inferred in recursive function

I'm still trying to figure out how to split code when using mirage and it's myriad of first class modules.
I've put everything I need in a big ugly Context module, to avoid having to pass ten modules to all my functions, one is pain enough.
I have a function to receive commands over tcp :
let recvCmds (type a) (module Ctx : Context with type chan = a) nodeid chan = ...
After hours of trial and errors, I figured out that I needed to add (type a) and the "explicit" type chan = a to make it work. Looks ugly, but it compiles.
But if I want to make that function recursive :
let rec recvCmds (type a) (module Ctx : Context with type chan = a) nodeid chan =
Ctx.readMsg chan >>= fun res ->
... more stuff ...
|> OtherModule.getStorageForId (module Ctx)
... more stuff ...
recvCmds (module Ctx) nodeid chan
I pass the module twice, the first time no problem but
I get an error on the recursion line :
The signature for this packaged module couldn't be inferred.
and if I try to specify the signature I get
This expression has type a but an expression was expected of type 'a
The type constructor a would escape its scope
And it seems like I can't use the whole (type chan = a) thing.
If someone could explain what is going on, and ideally a way to work around it, it'd be great.
I could just use a while of course, but I'd rather finally understand these damn modules. Thanks !
The pratical answer is that recursive functions should universally quantify their locally abstract types with let rec f: type a. .... = fun ... .
More precisely, your example can be simplified to
module type T = sig type t end
let rec f (type a) (m: (module T with type t = a)) = f m
which yield the same error as yours:
Error: This expression has type (module T with type t = a)
but an expression was expected of type 'a
The type constructor a would escape its scope
This error can be fixed with an explicit forall quantification: this can be done with
the short-hand notation (for universally quantified locally abstract type):
let rec f: type a. (module T with type t = a) -> 'never = fun m -> f m
The reason behind this behavior is that locally abstract type should not escape
the scope of the function that introduced them. For instance, this code
let ext_store = ref None
let store x = ext_store := Some x
let f (type a) (x:a) = store x
should visibly fail because it tries to store a value of type a, which is a non-sensical type outside of the body of f.
By consequence, values with a locally abstract type can only be used by polymorphic function. For instance, this example
let id x = x
let f (x:a) : a = id x
is fine because id x works for any x.
The problem with a function like
let rec f (type a) (m: (module T with type t = a)) = f m
is then that the type of f is not yet generalized inside its body, because type generalization in ML happens at let definition. The fix is therefore to explicitly tell to the compiler that f is polymorphic in its argument:
let rec f: 'a. (module T with type t = 'a) -> 'never =
fun (type a) (m:(module T with type t = a)) -> f m
Here, 'a. ... is an universal quantification that should read forall 'a. ....
This first line tells to the compiler that the function f is polymorphic in its first argument, whereas the second line explicitly introduces the locally abstract type a to refine the packed module type. Splitting these two declarations is quite verbose, thus the shorthand notation combines both:
let rec f: type a. (module T with type t = a) -> 'never = fun m -> f m

How to declare an abstract function in Inox

I'm proving certain properties on elliptic curves and for that I rely on some functions that deal with field operations. However, I don't want Inox to reason about the implementation of these functions but to just assume certain properties on them.
Say for instance I'm proving that the addition of points p1 = (x1,y1) and p2 = (x2,y2) is commutative. For implementing the addition of points I need a function that implements addition over its components (i.e. the elements of a field).
The addition will have the following shape:
val addFunction = mkFunDef(addID)() { case Seq() =>
val args: Seq[ValDef] = Seq("f1" :: F, "f2" :: F)
val retType: Type = F
val body: Seq[Variable] => Expr = { case Seq(f1,f2) =>
//do the addition for this field
}
(args, retType, body)
}
For this function I can state properties such as:
val addAssociative: Expr = forall("x" :: F, "y" :: F, "z" :: F){ case (x, y, z) =>
(x ^+ (y ^+ z)) === ((x ^+ y) ^+ z)
}
where ^+ is just the infix operator corresponding to add as presented in this other question.
What is a proper expression to insert in the body so that Inox does not assume anything on it while unrolling?
There are two ways you can go about this:
Use a choose statement in the body of addFunction:
val body: Seq[Variable] => Expr = {
choose("r" :: F)(_ => E(true))
}
During unrolling, Inox will simply replace the choose with a fresh
variables and assume the specified predicate (in this case true) on
this variable.
Use a first-class function. Instead of using add as a named function,
use a function-typed variables:
val add: Expr = Variable(FreshIdentifier("add"), (F, F) =>: F)
You can then specify your associativity property on add and prove the
relevant theorems.
In your case, it's probably better to go with the second option. The issue with proving things about an addFunction with a choose body is that you can't substitute add with some other function in the theorems you've shown about it. However, since the second option only shows things about a free variable, you can then instantiate your theorems with concrete function implementations.
Your theorem would then look something like:
val thm = forallI("add" :: ((F,F) =>: F)) { add =>
implI(isAssociative(add)) { isAssoc => someProperty }
}
and you can instantiate it through
val isAssocAdd: Theorem = ... /* prove associativity of concreteAdd */
val somePropertyForAdd = implE(
forallE(thm)(\("x" :: F, "y" :: F)((x,y) => E(concreteAdd)()(x, y))),
isAssocAdd
)

Can I avoid committing to particular types in a module type and still get pattern matching?

I have two module types:
module type ORDERED =
sig
type t
val eq : t * t -> bool
val lt : t * t -> bool
val leq : t * t -> bool
end
module type STACK =
sig
exception Empty
type 'a t
val empty : 'a t
val isEmpty : 'a t -> bool
val cons : 'a * 'a t -> 'a t
val head : 'a t -> 'a
val tail : 'a t -> 'a t
val length : 'a t -> int
end
I want to write a functor which "lifts" the order relation from the basic ORDERED type to STACKs of that type. That can be done by saying that, for example, two stacks of elements will be equal if all its individual elements are equal. And that stacks s1 and s2 are s.t. s1 < s2 if the first of each of their elements, e1 and e2, are also s.t. e1 < e2, etc.
Now, if don't commit to explicitly defining the type in the module type, I will have to write something like this (or won't I?):
module StackLift (O : ORDERED) (S : STACK) : ORDERED =
struct
type t = O.t S.t
let rec eq (x,y) =
if S.isEmpty x
then if S.isEmpty y
then true
else false
else if S.isEmpty y
then false
else if O.eq (S.head x,S.head y)
then eq (S.tail x, S.tail y)
else false
(* etc for lt and leq *)
end
which is a very clumsy way of doing what pattern matching serves so well. An alternative would be to impose the definition of type STACK.t using explicit constructors, but that would tie my general module somewhat to a particular implementation, which I don't want to do.
Question: can I define something different above so that I can still use pattern matching while at the same time keeping the generality of the module types?
As an alternative or supplement to the other access functions, the module can provide a view function that returns a variant type to use in pattern matching.
type ('a, 's) stack_view = Nil | Cons of 'a * 's
module type STACK =
sig
val view : 'a t -> ('a , 'a t) stack_view
...
end
module StackLift (O : ORDERED) (S : STACK) : ORDERED =
struct
let rec eq (x, y) =
match S.view x, S.view y with
Cons (x, xs), Cons (y, ys) -> O.eq (x, y) && eq (xs, ys)
| Nil, Nil -> true
| _ -> false
...
end
Any stack with a head and tail function can have a view function too, regardless of the underlying data structure.
I believe you've answered your own question. A module type in ocaml is an interface which you cannot look behind. Otherwise, there's no point. You cannot keep the generality of the interface while exposing details of the implementation. The only thing you can use is what's been exposed through the interface.
My answer to your question is yes, there might be something you can do to your definition of stack, that would make the type of a stack a little more complex, thereby making it match a different pattern than just a single value, like (val,val) for instance. However, you've got a fine definition of a stack to work with, and adding more type-fluff is probably a bad idea.
Some suggestions with regards to your definitions:
Rename the following functions: cons => push, head => peek, tail => pop_. I would also add a function val pop : 'a t -> 'a * 'a t, in order to combine head and tail into one function, as well as to mirror cons. Your current naming scheme seems to imply that a list is backing your stack, which is a mental leak of the implementation :D.
Why do eq, lt, and leq take a pair as the first parameter? In constraining the type of eq to be val eq : 'a t * 'a t -> 'a t, you're forcing the programmer that uses your interface to keep around one side of the equality predicate until they've got the other side, before finally applying the function. Unless you have a very good reason, I would use the default curried form of the function, since it provides a little more freedom to the user (val eq : 'a t -> 'a t -> 'a t). The freedom comes in that they can partially apply eq and pass the function around instead of the value and function together.