I have a function with the following signature:
val func : a -> b -> c -> d -> e -> f -> unit
and sometimes it raises exceptions. I want to change the control flow so that it looks like this:
val funcw : a -> b -> c -> d -> e -> f -> [ `Error of string | `Ok of unit ]
The way I tried wrapping it is ugly: make another function, funcw, that takes the same amount of arguments, applies func to them, and does try/with. But there must be a better way than that. Thoughts?
You can make f a parameter of the wrapper function. That's a little more general.
let w6 f a b c d e g =
try `Ok (f a b c d e g) with e -> `Error (Printexc.to_string e)
A wrapped version of func is then (w6 func)
This wrapper works for curried functions of 6 arguments, like your func. You can't really define a single wrapper for all the different numbers of arguments (as they have different types), but you can define a family of wrappers for different numbers of arguments like this:
let w1 f x = try `Ok (f x) with e -> `Error (Printexc.to_string e)
let ws f x y =
match f x with
| `Ok f' -> (try `Ok (f' y) with e -> `Error (Printexc.to_string e))
| `Error _ as err -> err
let w2 f = ws (w1 f)
let w3 f x = ws (w2 f x)
let w4 f x y = ws (w3 f x y)
let w5 f x y z = ws (w4 f x y z)
let w6 f x y z w = ws (w5 f x y z w)
There might be a tidier scheme but this seems pretty good.
Related
Let's assume I have a function f in Haskell, It takes a Double and returns a Double, and I have function g that also takes a Double and returns a Double.
Now, I can apply f to g like this: f . g.
Now, let's take a higher-dimensional function f, that
takes two Doubles and outputs one:
f :: Double -> Double -> Double
or
f :: (Double, Double) -> Double
And I have two g functions as well:
g1 :: Double -> Double, g2 :: Double -> Double
Now, I want to compose the functions to get something like:
composition x = f (g1 x) (g2 x)
Can this be achieved just by using the dot (.) operator?
You can make use of liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c for this:
composition = liftA2 f g1 g2
Since a function is an applicative [src]:
instance Applicative ((->) r) where
pure = const
(<*>) f g x = f x (g x)
liftA2 q f g x = q (f x) (g x)
and liftA2 is implemented as [src]:
liftA2 :: (a -> b -> c) -> f a -> f b -> f c
liftA2 f x = (<*>) (fmap f x)
this will thus be resolved to:
liftA2 f g1 g2 x = (<*>) (fmap f g1) g2 x
= (fmap f g1 <*> g2) x
= (f . g1 <*> g2) x
= (\fa ga xa -> fa xa (ga xa)) (f . g1) g2 x
= (f . g1) x (g2 x)
= f (g1 x) (g2 x)
You can try this:
import Control.Arrow
composition = f . (g1 &&& g2)
(&&&) turns g1 :: a -> b and g2 :: a -> c into g1 &&& g2 :: a -> (b, c). Then you can apply normal composition.
Im trying to define the polymorphic type of the following function:
flip f x y = f y x
My thought was the following:
1st parameter of flip, f takes two arguments so (t1 -> t2 -> t3)
2nd parameter of flip, x is of type t1 because of the parameter t1 inside f function.
3rd parameter of flip, y which is of type t3 because of the parameter t3 inside f function.
I don't know the polymorphic type of the overall return.
But when I checked the type in the ghci, I get:
flip :: (t2 -> t1 -> t) -> t1 -> t2 -> t
Can someone please help go through this example was to whats happening here?
Thanks
Your second assumption is wrong:
2nd parameter of flip, x is of type t1 because of the parameter t1 inside f function.
Let us first analyze the function:
flip f x y = f y x
We see that flip has three arguments in the head. So we first make the type:
flip :: a -> (b -> (c -> d))
We will of course now aim to fill in the types. With:
f :: a
x :: b
y :: c
flip f x y :: d
We see on the right hand side:
(f y) x
So that means that f is a function that takes as input y. So that means that a is the same type as c -> e (or shorter a ~ c -> e).
So now:
flip :: (c -> e) -> (b -> (c -> d))
f :: (c -> e)
x :: b
y :: c
Furthermore we see that:
(f x) y
So the result of (f x) is another function, with as input y. So that means that e ~ b -> f. Thus:
flip :: (c -> (b -> f)) -> (b -> (c -> d))
f :: c -> (b -> f)
x :: b
y :: c
Finally we see that (f y) x is the result of flip f x y. So that means that the type of the result of (f y) x is the same type as d. So that means that f ~ d. Which thus means that:
flip :: (c -> (b -> d)) -> (b -> (c -> d))
Or if we drop some redundant brackets:
flip :: (c -> b -> d) -> b -> c -> d
This is just a matter of solving a system of equations. First, assign unknown types:
f : a1
x : a2
y : a3
Next, f is applied to y. So, f must be a function type with argument of the same type as y, that is
f : a1 = a3 -> a4
f y : a4
Similarily, f y is applied to x, so
f y : a4 = a2 -> a5
f y x : a5
Substituting this back, we get
f : a3 -> a2 -> a5
x : a2
y : a3
We can rename these types
t2 = a3
t1 = a2
t = a5
and get
f : t2 -> t1 -> t
x : t1
y : t2
The function body is f y x, which has type t = a5.
I can't understand why the following function works with 2 arguments even if we declare it with one param:
let rec removeFromList e = function
h :: t -> if h=e then h
else h :: removeFromList e t
| _ -> [];;
removeFromList 1 [1;2;3];;
You're declaring it with two parameters. The syntax:
let f = function ...
can be seen as a shortcut for
let f x = match x with
So, your definition is actually:
let rec removeFromList e lst = match lst with
h :: t -> if h=e then h else h :: removeFromList e
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) ;;
Suppose I have two functions, f:X->Y and g:Y*Y->Z.
I want to make a third function, h(a, b) = g(f(a), f(b)).
h a b = g (f a) (f b)
Is there any way to write it like h(a, b) = g*f (a, b)?
And what if h(a,b,c,d) = g2*g1*f2*f1 (a,b,c,d), where g_i takes 2 args?
Searching Hoogle for functions with the right signature reveals on from Data.Function. According to its documentation,
g `on` f
seems to be what you want.
The on combinator (in Data.Function, as pointed out by gspr in another answer) is defined by
g `on` f = \x y -> g (f x) (f y)
Which would allow you to write
h = g `on` f
You can make higher-dimensional generalizations of this, for example
g `on3` f = \x y z -> g (f x) (f y) (f z)
g `on4` f = \w x y z -> g (f w) (f x) (f y) (f z)
So that you could write
h = g `on3` f
There may be a way to write on3 and on4 in terms of on, but if there is I can't see it at the moment.
You may also find Arrows interesting. Here's one way to do it:
h g f a b = uncurry g ((f *** f) (a, b))
Which is equivalent to your example (except that g and f are not free) and on. Using:
definition of *** for functions:
(***) f g ~(x,y) = (f x, g y)
definition of uncurry:
uncurry f p = f (fst p) (snd p)
And substituting them into the original equation:
h g f a b = uncurry g (f a, f b) (used *** definition)
h g f a b = g (f a) (f b) (used uncurry definition)