Pergunta

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)

Foi útil?

Solução 2

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.

Outras dicas

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:

  1. Raise an exception
  2. 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 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) ;; 
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top