4

It seems I'm using over and over a pattern that I would like to abstract as a function. The idea behind the pattern is that maybe I have something and if not I can try to produce it. Here is some OCaml code for the function I'm interested in naming, but the problem isn't OCaml specific. I looked for a Haskell precedent but I haven't seen such a function in the Data.Maybe module and hoogle didn't help: http://www.haskell.org/hoogle/?hoogle=Maybe+b+-%3E+%28a+-%3E+Maybe+b%29+-%3E+a+-%3E+Maybe+b.

let my_function a f arg = match a with
  | None -> f arg
  | Some _ -> a

This is almost like having a default potential value, but it avoid the need for generating the default if we have a value already.

Edit:

The reason I need this type is that I have a combinatorial problem to solve and a set of heuristics to solve it (say h1 and h2). h1 is faster than h2. None of these heuristics is guaranteed to find a solution, though. So I chain them and try them in order. Something like

match my_function (h1 problem) h2 problem with
| None -> "bad luck"
| Some solution -> "hurray"
Abdallah
  • 335
  • 1
  • 7

4 Answers4

10

Sounds like Alternative pattern:

a <|> f arg

nlucaroni
  • 47,556
  • 6
  • 64
  • 86
Ankur
  • 33,367
  • 2
  • 46
  • 72
3

How about:

fromMaybe (f arg) a

See: http://www.haskell.org/hoogle/?hoogle=fromMaybe

Also, in Haskell, f arg only has a chance of being computed when a is Nothing due to Haskell being lazy, unlike OCaml.

DJG
  • 6,413
  • 4
  • 30
  • 51
  • 2
    See the comments on my answer; this doesn't have the correct type. The OP requested a function with type `Maybe b -> (a -> Maybe b) -> a -> Maybe b` whereas this has type `Maybe b -> (a -> b) -> a -> b`. You could correct it by writing `fromMaybe (f arg) (Just a)` instead. Now, I can't really fathom *why* the OP wants something with that type (I think your version is far more sensible), but the fact remains that that is what they asked for! – Chris Taylor Sep 27 '13 at 08:34
3

In Haskell notation, your function is essentially

func :: Maybe a -> (b -> Maybe a) -> b -> Maybe a
func a f arg = case a of
  Nothing -> f arg
  Just _  -> a

Notice that you only ever use the inputs f and arg in the combination f arg, so you can simplify to

helper :: Maybe a -> Maybe a -> Maybe a
helper a b = case a of
  Nothing -> b
  _       -> a

func a f arg = helper a (f arg)

That is, your helper produces a if it has a value, otherwise it produces b. But you can write that in terms of maybe from Data.Maybe

helper :: Maybe a -> Maybe a -> Maybe a
helper a b = maybe b id a

func a f arg = helper a (f arg)

and then if you wanted you could inline the definition of helper

func a f arg = maybe (f arg) id a

So I don't think you have a pattern that already exists, but it's a simple variation on the maybe function, that does already exist.

Chris Taylor
  • 46,912
  • 15
  • 110
  • 154
  • FWIW, this will work well in Haskell because `(f arg)` is evaluated lazily. In OCaml you'll have to be more careful. Additionally it would be neater to use `fromMaybe`, as another answer notes. – Tom Ellis Sep 27 '13 at 08:26
  • `fromMaybe` is too restrictive - its type is `fromMaybe :: a -> Maybe a -> a` so to get the behaviour the OP wants, you would have to define `func a f arg = fromMaybe (f arg) (Just a)`, i.e. wrapping your argument `a :: Maybe a` in another layer of `Maybe`, which seems terribly ugly to me. – Chris Taylor Sep 27 '13 at 08:30
1

Looking at the general problem as described in your edit, maybe you'd be interested in something like (Uses OCaml Core library):

let heuristics = [lazy(h0 "problem"); lazy(h1 "problem"); lazy(h2 "problem")];;
let result = List.find heuristics (fun z -> Option.is_some (Lazy.force z));;

Just create a list of your heuristics up front and then find the first one that generates a valid solution.

Dave L.
  • 9,595
  • 7
  • 43
  • 69