Handle Exception: Failure "nth" - ocaml

In Python, it is quite simple to manage certain error with unit tests. For instance, to verify if a list is emptied or not, I can use assert test != []
Suppose the empty list let test = [];;
try
ignore (nth test 0)
with
Not_found -> print_string("Erreur!");;
Exception: Failure "nth"
I need to raise an error - print_string ("Erreur!") when I encounter Exception: Failure "nth". So far the try/with did not really help me. In Ocaml, is there a workaround to raise the error and print something when I get Exception: Failure "nth"?

In Python, it is quite simple to manage certain error, with unit tests. For instance, to verify if a list is emptied or not, I can use assert test != []
You can do exactly the same (modulo syntax) in OCaml
let require_non_empty xs =
assert (xs <> [])
If you would like to hush an exception and raise in its absence, you can use the match construction, here is how your example could be expressed in OCaml,
let require_empty xs = match List.nth xs 0 with
| exception _ -> ()
| _ -> failwith "the list shall be empty"
In addition, testing frameworks, e.g., OUnit2, provide special functions such as assert_raises for these specific cases.

You seem to be asking whether you can test for specific exceptions. Yes. The exception handling part after with is a list of patterns similar to the match expression.
try
ignore (List.nth [] 0)
with
| Not_found -> ()
| Failure s -> print_string ("Erreur: " ^ s)
| _ -> ()
(It probably isn't wise to depend on the exact string supplied as the argument to Failure. The compiler, in fact, warns you not to do this.)
OCaml also has an asssert expression:
# let list = [] in assert (List.length list > 0);;
Exception: Assert_failure ("//toplevel//", 1, 17).
You can use try/with to handle the resulting exception, of course. The argument to Assert_failure gives the filename, line number, and character number on the line.

Related

F# If statement type mismatch

i am in a bit of a pickle, i have tried for 2 hours straight trying to get this code to work and im lost.
let DropColumn list =
if List.exists List.isEmpty list then "empty value"
else
list |> List.map List.tail
This gives me an error error FS0001: The type 'string' does not match the type ''a list'
The usual way to deal with failure in functional programming is to use the Result type, which is essentially defined as:
type Result<'T,'TError> =
| Ok of 'T
| Error of 'TError
To apply it to your code we can just wrap the string in the unhappy path with Error and the list from the happy path with Ok:
let DropColumn list =
if List.exists List.isEmpty list then
Error "empty value"
else
list |> List.map List.tail |> Ok
Then to use it you can use pattern matching:
match DropColumn myList with
| Ok newList ->
newList
| Error message ->
printfn "Error occurred: %s" message
[]
The answer given by #glennsl is correct and in many cases the preferred way. However, I'd like to add that there are two other common ways of dealing with invalid input:
Raise an exception. Use this for exceptional cases only, i.e. where you expect your code to halt as the result of invalid data. Do not use it for normal validation where you expect that data can often be wrong.
Use option. This is similar to using Result, but doesn't maintain information for the invalid case. This approach is very common and used a lot in library functions like List.tryFind, List.tryHead etc.
Raise an exception
In the comments you show you already know this option exists, but let's give it here for completeness:
let dropColumnOrRaise list =
if List.exists List.isEmpty list then failwith "empty value"
else
list |> List.map List.tail
Use option
This method usually requires that the business logic that shows an error or does recovery, goes elsewhere.
let tryDropColumn list =
if List.exists List.isEmpty list then None
else
list
|> List.map List.tail
|> Some
Use it as follows:
match tryDropColumn myCols with
| Some columns ->
// do something with valid columns, i.e., display them
printfn "%i columns remaining (List.length (List.head myCols))"
| None ->
// error recovery or showing a message
printfn "No column selected"
When you are dealing with several functions that operate on data that all return option, you can pipe them together with Option.bind (or Option.map if a function doesn't return option).
myCols
|> tryDropColumn
|> Option.map logColumns // function that always succeeds
|> Option.bind tryAtLeastTwoColumns // function that returns None on 1 or 0
|> Option.map showColumns
The code above removes the need to have a match x with for each returned option. Similar code can be used for Result from the previous answer.

why the use of _ prevent having warnings

I have the following code (it's a test so it does nothing interesting)
let test k =
let rec aux = function
|0 -> 0
|z when z = 2 -> raise Exit
|_ -> aux (k-1)
in try let _ = aux k in true
with Exit -> false
At the end there is the use of the syntax : let _, to me it's just a syntax when you don't have an idea of a name you can use to define your function.
Yet if I do the following :
let test k =
let rec aux = function
|0 -> 0
|z when z = 2 -> raise Exit
|_ -> aux (k-1)
in try let b = aux k in true
with Exit -> false
I get a warning like : "variable b is unused", I don't understand why there is a difference between let _ and let b ?
For example I know that when dealing with unit type it's common to use the syntax : let (). Yet I don't have any warning when doing :
let b = print_int 2
even if I am not using :
let () = print_int 2
So what is particular with let _ ?
Thank you !
This is a convention, recognized by the compiler, to indicate that you're not going to use the result of a computation, e.g.,
let a = 5 + 6 in
()
will (or will not, depending on your warning settings) trigger the unused variable warning, since you clearly bound the result to a variable a, but not using it in the rest of your computation. In imperative languages it is quite common, to compute expressions for their side effects and ignore produced values if any. Since OCaml is a functional language, in which values are used to produce values, it usually an indicator of an error, when you forgot to use a bound variable.
Therefore, to explicitly tell the compiler that you're ignoring the value, you may start your variable with the underscore, e.g.,
let _unusued = 5 + 6 in
()
You can just use a wild pattern _ (which also starts with the underscore).
You have a warning with your second code because you define the variable b containing a value and you do not use it after.
The best use if you do not want to use the result of any expression is to discard its result using the 'let _ =' construct (it tells you want the expression to be evaluated, for potential side effects, but do not care to keep its result).
For the second part of your question, I think there are different rules related to the top loop, so the behaviours may not be comparable. In the first part, you define b inside a function and in the second part, you define b inside the top loop. In the top loop, you may define variables you will not use without getting a warning.

OCaml - Creating a function which prompts for floats and returns a list of floats

I'm teaching myself OCaml and I sometimes need to create a function where I'm not really sure what the proper solution should be. Here's one that I'm a little confused about.
I need a function that will prompt the user for individual float values and return everything entered in a float list. I can create this function but I'm not sure if its the proper/best way to do it in Ocaml.
Here's my attempt.
let rec get_floats() =
match
(
try Some(read_float())
with
| float_of_string -> None
)
with
| None -> []
| Some s -> s :: get_floats();;
This code works buts I'm at a loss deciding if its a 'proper OCaml' solution. Note, to exit the function and return the float list just enter a non-integer value.
(I hope that) this is a simple peephole rewrite involving no thought whatsoever of the function in your question:
let rec get_floats() =
try
let f = read_float() in (* as suggested by Martin Jambon *)
f :: (get_floats())
with
| float_of_string -> []
The idea I tried to apply here is that you do not need to convert the success/failure of read_float into an option that you immediately match: just do what you have to do with the value read, and let the with handle the failure case.
Now that I think of it, I should point out that in both your question and my rewrite, float_of_string is a fresh variable. If you meant to match a specific exception, you failed at it: all exception constructors, like datatype constructors, are Capitalized. You might as well have written with _ -> instead of with float_of_string ->, and a recent version of OCaml with all warnings active should tell you that your function (or mine) binds a variable float_of_string without ever using it.
Thanks everyone for the help. This works.
let rec get_floats() =
try
let x = read_float() in
x :: get_floats()
with
| _ -> [];;
List.iter (fun x -> print_endline(string_of_float x)) (get_floats());;

OCaml Option get

I'm new to OCaml, I'm trying to understand how you're supposed to get the value from an 'a option. According to the doc at http://ocaml-lib.sourceforge.net/doc/Option.html, there is a get function of type 'a option -> 'a that does what I want. but when I type:
# let z = Some 3;;
val z : int option = Some 3
# get z;;
Error: Unbound value get
# Option.get z;;
Error: Unbound module Option
Why isnt this working?
The traditional way to obtain the value inside any kind of constructor in OCaml is with pattern-matching. Pattern-matching is the part of OCaml that may be most different from what you have already seen in other languages, so I would recommend that you do not just write programs the way you are used to (for instance circumventing the problem with ocaml-lib) but instead try it and see if you like it.
let contents =
match z with
Some c -> c;;
Variable contents is assigned 3, but you get a warning:
Warning 8: this pattern-matching is not exhaustive. Here is an example
of a value that is not matched: None
In the general case, you won't know that the expression you want to look inside is necessarily a Some c. The reason an option type was chosen is usually that sometimes that value can be None. Here the compiler is reminding you that you are not handling one of the possible cases.
You can pattern-match “in depth” and the compiler will still check for exhaustivity. Consider this function that takes an (int option) option:
let f x =
match x with
Some (Some c) -> c
| None -> 0
;;
Here you forgot the case Some (None) and the compiler tells you so:
Warning 8: this pattern-matching is not exhaustive. Here is an example
of a value that is not matched: Some None
The usual way to do this is with pattern matching.
# let x = Some 4;;
val x : int option = Some 4
# match x with
| None -> Printf.printf "saw nothing at all\n"
| Some v -> Printf.printf "saw %d\n" v;;
saw 4
- : unit = ()
You can write your own get function (though you have to decide
what you want to do when the value is None).
You should listen to the above posters advice regarding type safety but also be aware that unsafe function such as Option.get (which is available in batteries btw) are usually suffixed with exn. If you're curious this is how Option.get or Option.get_exn could be implemented then:
let get_exn = function
| Some x -> x
| None -> raise (Invalid_argument "Option.get")

Getting error description from compiling regexp

I am trying to compile a regexp and get an error message that can be presented to the user. I tried this with Text.Regex.TDFA and Text.Regex.Posix and it seems to behave the same:
Prelude Text.Regex.TDFA Data.Maybe Data.Either.Utils> fromLeft $ (makeRegexM ".[" :: Either String Regex)
"*** Exception: parseRegex for Text.Regex.TDFA.String failed:".[" (line 1, column 3):
unexpected end of input
expecting "^", "]", "-" or Failed to parse bracketed string
Prelude Text.Regex.TDFA Data.Maybe Data.Either.Utils> isJust $ (makeRegexM ".[" :: Maybe Regex)
False
Prelude Text.Regex.TDFA Data.Maybe Data.Either.Utils> isJust $ (makeRegexM "." :: Maybe Regex)
True
The Maybe monad seems to work; the Either does not. However the documentation says, it should use 'fail' - which, as far as I know, is defined in Either monad. Am I doing something wrong?
The reason probably is that the monad instance for Either e recently changed. In mtl-1.*, there used to be an
instance Error e => Monad (Either e) where
...
fail msg = Left (strMsg msg) -- I may misremember the exact names
so calling fail there didn't cause an exception. Now, there is a monad instance in base (Control.Monad.Instances)
instance Monad (Either e) where
...
fail s = error s -- implicitly from the default method for fail
so you get the above.