Question

I want to easily take a value out of a "failable" data type or use a default in the case of failure.

Here's my implementation for Maybe:

infixr 1 <||>
(<||>) :: Maybe a -> a -> a
(<||>) = flip fromMaybe

pred :: String -> String -> Bool
pred x name = (x ==) <$> name `lookup` myMap <||> False

pred returns True if name maps to x in myMap.

But as is usually the case in Haskell, there is a more abstract way of doing this that I am unaware of. Anyone?

Was it helpful?

Solution

Foldable is probably a reasonable choice from the standard libraries:

import Data.Foldable

infixr 1 <||>
(<||>) :: Foldable f => f a -> a -> a

v <||> a =
    case toList v of
        [] -> a
        (x:xs) -> x

It does mean you have to decide whether to take the "first" element found or the "last" one though. Also unfortunately it doesn't yet have an Either instance, though it's coming in GHC 7.8/base 4.7. In the meantime you can define it yourself:

instance Foldable (Either a) where
    foldMap _ (Left _) = mempty
    foldMap f (Right y) = f y

    foldr _ z (Left _) = z
    foldr f z (Right y) = f y z

OTHER TIPS

Here's what I came up with:

class Defaultable f where
  infixr 1 <||>
  (<||>) :: f a -> a -> a

instance Defaultable Maybe where
  (<||>) = flip fromMaybe

instance Defaultable (Either a) where
  (Left _)  <||> x = x
  (Right x) <||> _ = x

Coupled with Alternative, you can string together possible choices with a default at the end.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top