{-| Declare an optional step by wrapping an existing arrow plan. The step will only
    be executed when the input is 'Just'.

    This function only makes sense when using the 'Arrow' instance of 'Plan',
    because for 'Applicative's an effect cannot depend on previously obtained
    values.

>>> :{
    let example :: Plan String () IO () ()
        example = proc () -> do 
            i <- step "reading" (plan (readMaybe @Int <$> getLine)) -< () 
            skippable "writing" (plan' print) -< i
    in  putStr . drawForest . fmap (fmap show) . toForest . mandatoriness . getSteps $ example
    :}
(Mandatory,"reading")
<BLANKLINE>
(Skippable,"writing")
<BLANKLINE>

-}
skippable :: (Monoid w,Monad m) => s -> Plan s w m i o -> Plan s w m (Maybe i) ()
skippable s (Plan forest (Star f)) = 
    Plan (Steps (Seq.singleton (mempty,s,Skippable,forest)) mempty) 
         (Star (\m -> case m of
                        Just x -> yield Started' *> f x *> yield Finished'
                        Nothing -> yield Skipped'))
skippable :: (Monoid w,Monad m) => s -> Plan s w m i o -> Plan s w m (Maybe i) ()
skippable s (Plan forest (Star f)) = 
    Plan (Steps (Seq.singleton (mempty,s,Skippable,forest)) mempty) 
         (Star (\m -> case m of
                        Just x -> yield Started' *> f x *> yield Finished'
                        Nothing -> yield Skipped'))
skippable s (Plan forest (Star f)) = 
    Plan (Steps (Seq.singleton (mempty,s,Skippable,forest)) mempty) 
         (Star (\m -> case m of
                        Just x -> yield Started' *> f x *> yield Finished'
                        Nothing -> yield Skipped'))