Reusing Variant handlers with default values of different types

Say I have an existing handler:

onFooOrBar :: forall v. (Variant v -> String) -> Variant (foo :: Int, bar :: Boolean | v) -> String
onFooOrBar = on _foo show >>> on _bar (if _ then "true" else "false")

I can use this with default and provide a value of the same return type:

default "" # onFooOrBar

Can I do something like this instead?

default Nothing # ?x <<< onFooOrBar

In short, not easily. on is CPSed, which means you must provide the alternative case that returns a string. Looking at the types:

(Variant v -> String) -> Variant (foo :: Int, bar :: Boolean | v) -> String

If you want to not provide something like “”, then the only thing you can do is pass in case_ (which is equivalent to absurd), and this fixes v to ().

onFooOrBar case_
  :: Variant (foo :: Int, bar :: Boolean) -> String

So if you then want to still keep the open v, you can contract it

map (onFooOrBar case_) <<< contract
  :: forall v. Variant (foo :: Int, bar :: Boolean | v) -> Maybe String

However there is currently no way to safely recover an alternative case for Variant v to keep the compositional nature of these handlers. To do that would require something like https://github.com/natefaubion/purescript-variant/issues/32

1 Like