You may not be able to accomplish exactly what you are asking for, but another possibility for your particular monad is to provide an action that clearly does what you are thinking of doing with Show . That is, suppose you have:
data M a = {- ... -} instance Monad M where -- notice: no Show constraint {- ... -}
Then you can additionally perform some actions:
report :: Show a => M a -> M a
I canβt come up with an example of using this template with Show , but I know a similar example where you can require an Ord constraint. The setup is that you would like to make a monad that is non-deterministic (for example, [a] ) but has no duplicates (for example, Set a ). Removing duplicates requires some context, such as Eq or Ord , but we cannot require this on every operation return / >>= . Therefore, instead, we require the user to explicitly indicate the points where duplicates should be combined:
newtype Setlike a = Setlike { toList :: [a] } instance Monad Setlike where return x = Setlike [x] Setlike xs >>= f = [y | x <- xs, let Setlike ys = fx, y <- ys] collapse :: Ord a => Setlike a -> Setlike a collapse = Setlike . Data.Set.toList . Data.Set.fromList . toList
This can be used like this:
valuesOfInterest = collapse $ do v1 <- allValues v2 <- allValues doSomethingInteresting v1 v2
Then, even if some pairing of v1 and v2 leads to the same value of interest, this value will appear only once as a result.
Some similar trick is probably possible for your use case.
source share