I would like to print a meaningful message when raising a defined exception in OCaml:
type t = A | B of int
exception Wrong of t
Say I have a function
let string_of_t = function
| A -> "A"
| B n -> ("B" ^ (string_of_int n))
Then I would like to have a function
val print_exception : ( 'a -> string ) -> a' exn -> string
so that I can define
let my_raise e =
print_endline ("Error: I got the unexpected value" ^ (print_exception string_of_t e));
raise e [???]
Is there such a function print_exception ?
The problem is not very well-posed (for instance, there is no a' exn type), but I hope my intent is understandable. I've seen that one can use [##deriving sexp] but this looks like some magic outside of the language, and there is probably something easier and within the language.
There are two ways. The first one is using Printexc, the second one would be to match all the exceptions you want to print and print accordingly, something like:
exception Zero of int
exception B of string
let pp ppf = function
| Zero d -> Format.fprintf ppf "Zero of %d" d
| B s -> Format.fprintf ppf "B of %s" s
| Not_found -> Format.fprintf ppf "Not found"
| _ -> Format.fprintf ppf "Your exception is in another castle"
let f n d = if d = 0 then raise (Zero d) else n / d
let () =
let n, d = (10, 0) in
try Format.printf "%d/%d is %d#." n d (f n d)
with e ->
Format.eprintf "%a#." pp e;
Format.eprintf "%s#." (Printexc.to_string e)
Will give
❯ ./exc
Zero of 0
Exc.Zero(0)
Combining the two seems to be the best solution to be able to customise some displays and let all the others be a default one:
let pp ppf = function
| Zero d -> Format.fprintf ppf "Zero of %d" d
| e -> Format.fprintf ppf "%s" (Printexc.to_string e)
In OCaml we don't have (yet) modular implicits so unless you use [##derive ...] you need to use one of the two solutions.
As a side-note, exceptions can be caught in a pattern matching:
let () =
let n, d = (10, 0) in
match f n d with
| r -> Format.printf "%d/%d is %d#." n d r
| exception e ->
Format.eprintf "%a#." pp e;
Format.eprintf "%s#." (Printexc.to_string e)
It does semantically the same as what I wrote before but it's better for call stacks (if I'm not mistaken)
[EDIT] Looks like I forgot a third solution, see #octachron's answer
If you want to log a meaningful message before raising, it seems to me that it might be simpler to combine the logging and exception raising in one function rather than trying to reconstruct an error message from a generic unknown exception after the fact. For instance, the following function
let log_and_raise exn fmt =
Format.kfprintf
(fun ppf -> Format.pp_print_newline ppf (); raise exn)
Format.err_formatter fmt
can be used like this
exception A of int
let test n = log_and_raise (A n) "Raising the exception (A %d)" n
and will raise the exception A n after printing the error message on stderr.
Related
I am tasked with finishing an interpreter in F#, but I'm having some trouble, as I im getting the error: error FS0588: The block following this 'let' is unfinished. Every code block is an expression and must have a result. 'let' cannot be the final code element in a block. Consider giving this block an explicit result.
Its been a long time since last time I programmed I F#.
The following is my code. I have a helper function inside my eval function, called OperateAux. It gets called in the pattern matching, when it matches e with OPERATE. It should then call OperateAux, and calculate the given expression. The error I'm getting is at line: let OperateAux (op:BINOP) (e1:EXP) (e2:EXP) : VALUE =
so I guess somehow my helper function isn't finished, I just cant figure out where.
let rec eval (vtab : SymTab) (e : EXP) : VALUE =
match e with
| CONSTANT n -> n
| VARIABLE v -> lookup v vtab
| OPERATE (op, e1, e2) -> OperateAux op e1 e2//(eval vtab e1) (eval vtab e2)
| LET_IN (var, e1, e2) -> failwith "case for LET_IN not handled"
| OVER (rop, var, e1, e2, e3) -> failwith "case for OVER not handled"
let OperateAux (op:BINOP) (e1:EXP) (e2:EXP) : VALUE =
let (INT e1) = eval vtab e1
let (INT e2) = eval vtab e2
match op with
| BPLUS -> (e1+e2)
| BMINUS -> (e1-e2)
| BTIMES -> (e1*e2)
| _ -> ()
Here is some types, I'm not sure if they are relevant for this question, but for good measure I'll show them.
type VALUE = INT of int
type BINOP = BPLUS | BMINUS | BTIMES
type RANGEOP = RSUM | RPROD | RMAX | RARGMAX
type EXP =
| CONSTANT of VALUE
| VARIABLE of string
| OPERATE of BINOP * EXP * EXP
| LET_IN of string * EXP * EXP
| OVER of RANGEOP * string * EXP * EXP * EXP
(* A list mapping variable names to their values. *)
type SymTab = (string * VALUE) list
Nevermind, I figured it out. You have to "initialise" your helper function before actually calling it. So the helper function operateAux should come before the pattern matching which calls it.
I'm learning F# and is doing an exercise that requires me to perform math operations on a stack of floats.
exception InterpreterError;;
type Instruction =
| ADD
| SUB
| MULT
| DIV
| SIN
| COS
| LOG
| EXP
| PUSH of float;;
type Stack = S of float list;;
let pop (S(s)) =
match s with
| [] -> raise InterpreterError
| x::_ -> (x,S(s));;
let push x (S(s)) : Stack = S(x::s)
let applyBin f s : Stack =
let (first, sGen1) = pop s
let (second,sGen2) = pop sGen1
push (f(first,second)) sGen2;;
let applyUni f s : Stack =
let (first, sGen1) = pop s
push (f(first)) sGen1;;
let intpInstr i s =
match i with
| ADD -> applyBin (+) s
| SUB -> applyBin (-) s
| MULT -> applyBin (*) s
| DIV -> applyBin (/) s
| SIN -> applyUni sin s
| COS -> applyUni cos s
| LOG -> applyUni log s
| EXP -> applyUni exp s
| PUSH(r) -> push r s;;
However, I'm getting a compiler error in the last function intpInstr on the infix operators (+, -, *, /) that I try to pass as arguments:
Type mismatch. Expecting a
float * float -> float
but given a
float * float -> 'a -> 'b
The type 'float' does not match the type ''a -> 'b'
Why does the operators become (+) : float -> float -> 'a -> 'b? I haven't been able to replicate this type in the interactive console.
All help appreciated.
With your definition of applyBin the parameter f has type (float * float) -> float i.e. it takes a single pair parameter and returns a float. This is due to the application f (first, second) in applyBin. The binary operators +, -, * and / all have type float -> float -> float so it looks like you intend that to be the type of f within applyBin. You can do this by removing the pair construction:
let applyBin f s : Stack =
let (first, sGen1) = pop s
let (second,sGen2) = pop sGen1
push (f first second) sGen2
If you're willing to invest into a custom composition operator, you could employ eta reduction and express the logic of the function application more succinctly.
let (>|>) f g = f >> fun (b, c) -> g b c
let applyUna f =
pop >|> fun first ->
push (f first)
let applyBin f =
pop >|> fun first ->
pop >|> fun second ->
push (f first second)
There are still two tupled arguments returned by the 'pop' operation. Their conversion to curried arguments enables partial application and avoids the need to name any of the stack states.
I have the following structure:
Terra [['0','1','0','1'],['0','1','0','1'],['1','0','G','1']]
and de function:
esTerra:: Taulell -> (Int,Int) -> Bool
esTerra t (u,d) =
case t!!!u!!!d of
Left e -> False
Right p -> True
(!!!) :: [a] -> Int -> Either Bool a
xs !!! n | n < 0 = Left False -- error Exception: Prelude.!!:...
[] !!! _ = Left False -- error Exception: Prelude.!!:...
(x:_) !!! 0 = Right x
(_:xs) !!! n = xs!!!(n-1)
the function !!! is equal the operation !! but when you have to return an error message returns False
but return error:
Couldn't match expected type ‘[a0]’
with actual type ‘Either Bool [Char]’
In the first argument of ‘(!!!)’, namely ‘t !!! u’
In the expression: t !!! u !!! d
In the expression:
case t !!! u !!! d of {
Left e -> False
Right p -> True }
Because?
Thank's
I don't know what Taulell is, let's guess Taulell = [[a]] for some a.
We have
t :: [[a]] -- Taulell
u :: Int
d :: Int
hence
t !!! u :: Either Bool [a]
Then we write
(t !!! u) !!! d
but here the leftmost argument is not a list, it's an Either Bool [a]. Hence a type error arises.
Instead, we could try, e.g.
case t !!! u of
Left b -> ...
Right l -> case l !!! d of
Left c -> ...
Rigth w -> ...
!!! needs a list as its left argument, but for a nested list it does not give a simple list as the result. It gives an Either Bool [a] as the result.
You can't use that again as the argument to !!!, but you can easily enough apply !!! to the Either-contained list:
esTerra:: Taulell -> (Int,Int) -> Bool
esTerra t (u,d) =
case t!!!u >>= (!!!d) of
Left e -> False
Right p -> True
Here, I've used the monadic bind operator >>= to combine two possibly-failing lookups into one, which will succeed only if both lookups do. This is equivalent to twice explicitly unwrapping the Either structure with a case construct, as shown by chi.
In OCaml, I have a list of strings that contains names of towns (Something like "1-New York; 2-London; 3-Paris"). I need to ask the user to type a number (if they want London they have to type 2).
I want to raise an exception message saying that the town is not valid, if the person types for example "4", in the example.
I tried this, but it doesn't work :
let chosenTown = match int_of_string (input_line stdin) with
| x > (length listOfTowns) -> raise (Err "Not a valid town")
What's the good way to code "if the chosen number is bigger than the length of the list then raise the error" ??
Pattern can't contain arbitrary expressions. It can be a constant, a constructor name, record field inside curly braces, list, array, etc.
But patterns can be guarded, e.g.
match int_of_string (input_line stding) with
| x when x >= length listOfTowns ->
invalid_arg "the number is too large"
| x -> List.nth listOfTowns x
To complete the answer, patter matching relies on unification and does not expect assertion (it is not the equivalent of a switch in C or so).
The idea is that you provide different "shapes" (patterns) that your term (the thing you match on) could have.
For a list for instance:
match l with
| e :: e' :: r -> (*...*)
| e :: r -> (*...*)
| [] -> (*...*)
It also had a binding effect, if you pass on, say, [1] (a very small list indeed), it won't match e :: e' :: r, but will match e :: r and then e = 1 and r = [].
As ivg said, you can add conditions, as booleans this time, thanks to the keyword when.
However, when manipulating lists like this, I would go for a recursive function:
let rec find_town n l =
match l with
| t :: _ when n = 1 -> t
| _ :: r -> find_town (n-1) r
| [] -> raise (Err "Not a valid town")
This is basically writing again List.nth but changing the exception that it raises.
I have to write the function try_finalyze f g y x of type : ('a -> 'b) -> ('b -> 'c) -> 'c -> 'a -> 'c
knowing that:
1. if an exception is raised by f x the returned value has to be y
2. if f x doesn't raise any exception we have to return the result of g applied on f x
exception E
let try_finalyze f g y x = try g (f x) with E -> y;;
val try_finalyze : ('a -> 'b) -> ('b -> 'c) -> 'c -> 'a -> 'c = <fun>
1.Is it right how I treated the problem?
2.In this context what will do the following function:
fun f -> try_finalyze f (fun x-> Some x) None
I don't see the role of a function like (fun x-> Some x)
The answer to your first question is - not really. According to your specification function should catch any exception, not only your exception E. Maybe I'm misreading, but it will be better use the following definition:
let try_finalize f g y x = try g (f x) with exn -> y
As for the second part of the question, there're several ways in OCaml to signal an error. The two most common are:
Raise an exception
Return a value of an option type
The former variant is syntactically lighter, the later doesn't allow a caller to ignore the error condition. Sometimes you need to switch from one variant to an another. Suppose you have a function that raises an exception, and you would like to create a function with the same behavior, but returning an option value. Let's give it a name:
let with_option f = try_finalize f (fun x-> Some x) None
Then we can, for example, convert a List.hd to a function that returns an option type, depending on whether the list is empty or not:
let head x = with_option List.hd x
This function will have type 'a list -> 'a option, compare it with List.hd type 'a list -> 'a, the former will not allow to ignore the empty list case. When applied to an empty list, it will return a None value:
# head [];;
- : 'a option = None
If you write
let try_finalize f g y x = try g (f x) with _ -> y
Your function will return y if f doesn't raise an error but g does, which is not what you said you want.
To ensure that you catch only errors from f you should put f x alone in the try block:
let try_finalize f g y x =
let z = try Some (f x) with _ -> None in
match z with
| Some z -> g z
| None -> y
Exceptions may be considered bad style in a purely functional code, that's why you may want to transform a function that may raise an exception such as List.assoc : 'a -> ('a * 'b) list -> 'b into a function that does the same thing but returns an option.
That's what
let with_option f = try_finalize f (fun x-> Some x) None
does.
If I understand the problem statement correctly, I think I would do this :
let try_finalize f g y x =
try
let v = f x in g v
with _ -> y
As for question 2, suppose you have a function f that takes a value of type v and computes a result of type r. This :
fun f -> try_finalize f (fun x-> Some x) None
returns a function that tries to apply f. If it succeeds (i.e. no exception is thrown), it returns Some r. Otherwise, it returns None. Basically, it transforms a function that may throw an exception into a function that will not throw anything. The new function returns a r option instead of a r.
Maybe like this but the function doesn't have anymore the required type
let try_finalyze f g y x = match f x with
|E -> y
| _ -> g (f x) ;;