Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Non-parser example for `Control.Applicative.optional`

I've recently stumbled over the generic Control.Applicative.optional combinator:

optional :: Alternative f => f a -> f (Maybe a)
optional v = Just <$> v <|> pure Nothing

but I don't much practical use for that combinator; e.g. when applied to pure functors such as lists or Maybe, the results don't seem very useful:

> optional [1,2,3]
[Just 1,Just 2,Just 3,Nothing]

> optional Nothing
Just Nothing

> optional (Just 1)
Just (Just 1)

...what would be more sensible applications of optional?

like image 824
hvr Avatar asked Feb 29 '12 14:02

hvr


1 Answers

It is useful for modelling any computation that is allowed to fail.

For example, let's say that you are dealing with STM and have these functions:

-- A database of Ints stored in a TVar
intDatabase :: TVar (ComplexDatabaseStructure Int)

-- Inserts an Int in the int database.
insertInt :: Int -> STM ()

-- Organizes the DB so that it is more efficient
optimizeDb :: STM ()

-- Checks whether an Int is in the DB
lookupInt :: Int -> STM Bool

Now, optimization is nice to do after inserts, but it isn't critical. So you could see this usage:

insert2AndCheck1 a b c =
  insertInt a *> insertInt b *> optional optimizeDb *> lookupInt c

This function inserts two ints, then tries to optimize the DB, but if it fails (because of STM reasons, like that someone was inserting something at the time), it isn't a big deal; we just go on anyways.

optional works with STM, and also any error monad in Control.Monad.Error, and a lot of different things; certainly also for pure computations.

like image 143
dflemstr Avatar answered Nov 11 '22 08:11

dflemstr