logoalt Hacker News

tometoday at 10:25 AM1 replyview on HN

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

Replies

mrkeentoday at 11:04 AM

"You can't" is simpler, because the inevitable reply is "but how do I do actual logging inside g"

show 1 reply