9 ms·
‘Non-IO functions can't call IO functions.’ How do you handle logging then? If f() calls g(), how can I add logging to g() without having to change or recompil
by captaincrowbar 4mo ago
‘Non-IO functions can't call IO functions.’
How do you handle logging then? If f() calls g(), how can I add logging to g() without having to change or recompile f() (and everything in the call stack above it)? ‘You can’t’ is not an acceptable answer.
- CuriousSkeptic 4mo agoYou can’t is an acceptable answer. The entitle point of such a feature is to prevent people from doing that.
- mrkeen 4mo agoDon't declare it as non-logging.
- tome 4mo agoNot sure why people are saying "you can't" when it seems to me the whole point of algebraic effects that you can. You can define g so that it has no ability to do "general IO", all it can do is yield log messages. Then f can call g in a way that turns the log messages into writes to stdout. For example, here's how you would do it in Bluefin: type Log = Yield String -- workWithLogging cannot do arbitrary IO! -- All it can do is yield log messages, which -- must be processed elsewhere. workWithLogging :: (e1 :> es) => Log e1 -> Int -> Int -> Eff es Int workWithLogging l x y = do yield l ("x was " <> show x) yield l ("y was " <> show y) let result = x + y yield l ("result was " <> show result) pure result -- ghci> example -- x was 5 -- y was 7 -- result was 12 -- 12 example :: IO Int example = runEff $ \io -> do -- forEach determines how each log message -- should be handled. forEach (\l-> workWithLogging l 5 7) (\logMsg -> effIO io (putStrLn logMsg))
- codebje 4mo agoIf `left_pad()` calls `send_env_vars()`, how can you add exfiltration to `send_env_vars()` without having to change `left_pad()` to expose the use of the network? "You can't" should be the ONLY acceptable answer.