Make apSubstMaybe
return a Changed
value (without Applicative
/Monad
instances)
#1775
Labels
cryptol-as-a-library
Uses of Cryptol from Haskell
tech-debt
For issues that require some internal refactoring.
A common pitfall when defining substitution-related functions with the Cryptol API is to do something like this:
(Where
apSubstMaybe :: Subst -> Type -> Maybe Type
.)This is subtly wrong, however. The
Maybe
inapSubstMaybe
's return type is meant to beNothing
if applying the substitution did not change anything, and it is meant to beJust
if applying the substituion did change something. However, due to the way theApplicative Maybe
instance works,x <*> y = Nothing
whenx
ory
isNothing
, even if the other value isJust
. This means that with the waysubstFoo
is defined above, it could erroneously returnNothing
, even if the substitution changes one ofx
ory
!The immediate problem can be fixed by rewriting the code to be in terms of
anyJust2
:However, it is still all too tempting to accidentally use the
Applicative Maybe
instance (or theMonad Maybe
instance, which has similar short-circuiting behavior forNothing
values) when defining custom substitution functions. In fact, this is a mistake that even thecryptol
codebase has made before! Ideally, we'd make it harder for users to stumble into this pitfall. To that end, I propose that we changeapSubstMaybe
to instead returnChanged Type
, whereChanged
is defined as:Moreover,
Changed
would intentionally not haveApplicative
orMonad
instances: the only way to composeChanged
values would be with combinators such asanyJust2
(which would also need to manipulateChanged
values instead ofMaybe
values). At that point, we might also consider renaming some of these functions, since they would no longer useMaybe
,Just
, etc.This would be a breaking change for users of the Cryptol API, so we should make sure to survey what the breakage would be before landing such a change.
The text was updated successfully, but these errors were encountered: