Safe Haskell | Safe-Inferred |
---|
Consider this peace of code:
join $ atomically $ do radarPositive <- readTVar radarTVar launchKeyInserted <- readTVar launchKeyTVar case radarPositive of False -> do modifyTVar radarNegativeCounter (+1) return $ print "No need for missiles, it's peaceful" True -> do modifyTVar radarPositiveCounter (+1) case launchKeyInserted of False -> do modifyTVar keyMissingCounter (+1) return $ print "No launch key, ignoring radar" True -> do modifyTVar launchCounter (+1) return $ launchMissiles return $ print "extra debug: state checking finished"
We use STM
to make state checking of multiple TVar
s one atomic
transaction. Since we can't do IO
in STM
, we are just returning
the IO
that needs to be done in the different cases. Unfortunately
when we try to add the extra debugging as the last statement, that
silently ignores all the previous "return" values, even
launchMissiles
.
On the other hand when using final:
atomicJoinFinal $ do radarPositive <- readTVar radarTVar launchKeyInserted <- readTVar launchKeyTVar case radarPositive of False -> do modifyTVar radarNegativeCounter (+1) final $ print "No need for missiles, it's peaceful" True -> do modifyTVar radarPositiveCounter (+1) case launchKeyInserted of False -> do modifyTVar keyMissingCounter (+1) final $ print "No launch key, ignoring radar" True -> do modifyTVar launchCounter (+1) final $ launchMissiles final $ print "extra debug: state checking finished"
We get a compile error that contains this:
Note: there are several potential instances: instance FinalClass Control.Final.FinalTooManyReturns
Internally Final
is based on ambiguity checking in the type
system. The prohibited ambiguity occurs, because the only way to
decide what final
means is by matching it to the corresponding
atomicJoinFinal
. This is now only possible for the final
at
the end of the function and not for the middle ones, so we get the
error.