← Back to context

Comment by mrkeen

11 hours ago

No, they are function colouring. That's the point.

Someone writes a post lamenting red and blue functions, and everyone eats it up.

Substitute colour for something meaningful and the idea becomes idiotic.

"Top level function declares that it is non-blocking, but when I try to call a small blocking function from it, I have to change the declaration to blocking???"

Yes, yes you do.

Total functions can't call non-total functions.

Deterministic functions can't call nondeterministic functions.

Non-IO functions can't call IO functions.

‘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.

  • Not 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))

  • You can’t is an acceptable answer. The entitle point of such a feature is to prevent people from doing that.