> > Admittedly I don't really understand what RT is, but from what I > understand, in Haskell the expression like [print "ha"] is basically a > command to the top-level interpreter (which is the language runtime) to > perform an effect on the console (moreover, it will be evaluated on > as-needed basis). >
> > I like to imagine an interpreter that sits in the Haskell's runtime. > Values of IO type are commands to this interpreter. Typical Haskell > IO-based programs are building up these commands as they are being > evaluated by the runtime. The runtime starts evaluation at the "main" > expression defined by the programmer. > You are describing "Free-monad", which is an AST interpreter in runtime, but the actual *IO-action* in haskell is newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #)) which means, that Haskell models IO as "some function, that takes RealWorld state, possibly modifies it and returns new RealWorld state and some value", `newtype` is a compile-time abstraction, which will be optimized out and will be represented as a field, which is a function. State# is a `primitive` datatype (provided by runtime) (# #) is a primitive tuple So when you write main :: IO () main = putStrLn "hello" it is actually a function, that needs `State# RealWorld` value in order to produce value of type () (unit): putStrLn :: String-> IO () putStrLn str = IO $ \state0-> case ffi_call_to_putStrLn str of IO next-> -- here we bind function of `ffi_call_to_putStrLn` as `next` case next state0 of -- evaluate `next` here as it now has `s` argument (# state1, () #) -> (# state1, () #) -- force evaluation of `next`, as this pattern match is strict main :: IO () main = IO $ \state0-> case putStrLn "hello" of IO next-> -- here we bind function of `putStrLn` as `next` case next state0 of -- evaluate `next` here as it now has `s` argument (# state1, () #)-> (# state1, () #) -- force evaluation of `next`, as this pattern match is strict Moreover, the ";" is itself another comand, the explicit sequencing > command, the meaning of which is "perform the left-hand side effects, then > perform the right-hand side effects". Such a command is a value, so it can > be passed as a value and reused as many times as is necessary. In ATS, the > expression like [print "ha"] evaluates right there to a void/"no value", > and the ";" is also NOT a value at all, but rather a "shortcut" syntax to a > "let-in-end" form. > In haskell, this is (>>=) (bind) function: class Monad base where (>>=) :: base left_type-> (left_type-> base right_type)-> base right_type (>>) :: base left_type-> (left_type-> base right_type)-> base right_type (>>) first second = first >>= \_ -> second instance Monad IO where (>>=) (IO first) second = IO $ \state0-> case first state0 of (# state1, first_value #)-> case second first_value of IO next-> next state1 And thus, in haskell: main = do let shortcut = putStrLn "hello" shortcut shortcut will print "hello" twice, as shortcut is a function, which needs 1 argument to be evaluated. Desugared version: main = let shortcut = putStrLn "hello" in shortcut >> shortcut which is: main = IO $ \state0-> let shortcut = putStrLn "hello" in case (shortcut >> shortcut) state0 of (# state1, () #)-> (# state1, () #) So, being pure, Haskell pretends that "program is started with some unknown RealWorld state of value0 and each IO action modifies this state and thus, this value is unique for all expressions and thus. complier should evaluate them all instead of caching result of the first evaluation of `hostcut`" -- You received this message because you are subscribed to the Google Groups "ats-lang-users" group. To unsubscribe from this group and stop receiving emails from it, send an email to ats-lang-users+unsubscr...@googlegroups.com. To post to this group, send email to ats-lang-users@googlegroups.com. Visit this group at https://groups.google.com/group/ats-lang-users. To view this discussion on the web visit https://groups.google.com/d/msgid/ats-lang-users/a6a6c026-9659-413a-895e-485249ecc6a1%40googlegroups.com.