interpretWith :: forall m a. Monad m => Environment m -> FormatM a -> m a
interpretWith Environment{..} = go
  where
    go :: forall b. FormatM b -> m b
    go m = case m of
      Pure value -> return value
      Free action -> case action of
        GetSuccessCount next -> environmentGetSuccessCount >>= go . next
        GetPendingCount next -> environmentGetPendingCount >>= go . next
        GetFailMessages next -> environmentGetFailMessages >>= go . next
        UsedSeed next -> environmentUsedSeed >>= go . next
        PrintTimes next -> environmentPrintTimes >>= go . next
        GetCPUTime next -> environmentGetCPUTime >>= go . next
        GetRealTime next -> environmentGetRealTime >>= go . next
        Write s next -> environmentWrite s >> go next
        WriteTransient s next -> environmentWriteTransient s >> go next
        WithFailColor inner next -> environmentWithFailColor (go inner) >>= go . next
        WithSuccessColor inner next -> environmentWithSuccessColor (go inner) >>= go . next
        WithPendingColor inner next -> environmentWithPendingColor (go inner) >>= go . next
        WithInfoColor inner next -> environmentWithInfoColor (go inner) >>= go . next
        UseDiff next -> environmentUseDiff >>= go . next
        ExtraChunk s next -> environmentExtraChunk s >> go next
        MissingChunk s next -> environmentMissingChunk s >> go next
        LiftIO inner next -> environmentLiftIO inner >>= go . next

-- | Get the number of successful examples encountered so far.
interpretWith :: forall m a. Monad m => Environment m -> FormatM a -> m a
interpretWith Environment{..} = go
  where
    go :: forall b. FormatM b -> m b
    go m = case m of
      Pure value -> return value
      Free action -> case action of
        GetSuccessCount next -> environmentGetSuccessCount >>= go . next
        GetPendingCount next -> environmentGetPendingCount >>= go . next
        GetFailMessages next -> environmentGetFailMessages >>= go . next
        UsedSeed next -> environmentUsedSeed >>= go . next
        PrintTimes next -> environmentPrintTimes >>= go . next
        GetCPUTime next -> environmentGetCPUTime >>= go . next
        GetRealTime next -> environmentGetRealTime >>= go . next
        Write s next -> environmentWrite s >> go next
        WriteTransient s next -> environmentWriteTransient s >> go next
        WithFailColor inner next -> environmentWithFailColor (go inner) >>= go . next
        WithSuccessColor inner next -> environmentWithSuccessColor (go inner) >>= go . next
        WithPendingColor inner next -> environmentWithPendingColor (go inner) >>= go . next
        WithInfoColor inner next -> environmentWithInfoColor (go inner) >>= go . next
        UseDiff next -> environmentUseDiff >>= go . next
        ExtraChunk s next -> environmentExtraChunk s >> go next
        MissingChunk s next -> environmentMissingChunk s >> go next
        LiftIO inner next -> environmentLiftIO inner >>= go . next

-- | Get the number of successful examples encountered so far.
interpretWith Environment{..} = go
  where
    go :: forall b. FormatM b -> m b
    go m = case m of
      Pure value -> return value
      Free action -> case action of
        GetSuccessCount next -> environmentGetSuccessCount >>= go . next
        GetPendingCount next -> environmentGetPendingCount >>= go . next
        GetFailMessages next -> environmentGetFailMessages >>= go . next
        UsedSeed next -> environmentUsedSeed >>= go . next
        PrintTimes next -> environmentPrintTimes >>= go . next
        GetCPUTime next -> environmentGetCPUTime >>= go . next
        GetRealTime next -> environmentGetRealTime >>= go . next
        Write s next -> environmentWrite s >> go next
        WriteTransient s next -> environmentWriteTransient s >> go next
        WithFailColor inner next -> environmentWithFailColor (go inner) >>= go . next
        WithSuccessColor inner next -> environmentWithSuccessColor (go inner) >>= go . next
        WithPendingColor inner next -> environmentWithPendingColor (go inner) >>= go . next
        WithInfoColor inner next -> environmentWithInfoColor (go inner) >>= go . next
        UseDiff next -> environmentUseDiff >>= go . next
        ExtraChunk s next -> environmentExtraChunk s >> go next
        MissingChunk s next -> environmentMissingChunk s >> go next
        LiftIO inner next -> environmentLiftIO inner >>= go . next

-- | Get the number of successful examples encountered so far.