From posting-system@google.com Tue Aug 26 19:01:47 2003 Date: Tue, 26 Aug 2003 12:00:45 -0700 From: oleg-at-pobox.com Newsgroups: comp.lang.scheme Subject: Re: monads and reflection [was: overloading] References: <7eb8ac3e.0308251027.4773d026@posting.google.com> Message-ID: <7eb8ac3e.0308261100.493e0906@posting.google.com> X-Comment: slight editing. Status: OR "David A. Herman" wrote in message news:... > I've heard some warnings about the constructions this paper uses, > namely monadic reflection. Monadic reflection is the "running" of a monad. When you see "runST", for example, in Haskell code, you see the monadic reflection. The function getChar, for example, is the result of a reification of an I/O action. The function represents an effect as a pure value (IO Char). The function unsafePerformIO turns (i.e., reflects) that value into an effect. Filinski uses a slightly different notation for bind: he writes "m >>= f" as "f* m" (that is, he flips the operands). That notation might be less convenient for practical applications, but far more insightful. Indeed, we can read '*' as a binary operator: (*):: (a->M b) -> M a -> M b OTH, we may consider (*) as an unary postfix operator. Then "(f*) m" is a regular application. That postfix (*) has the type (*):: (a->b) -> (M a -> M b) which is just fmap. If we have a function f::a->b that takes a to b and has an effect, we get the monadic (lifted) function f*:: M a -> M b as f* = \m -> reify(f (reflect m)) The function f* no longer _does_ any effects: it merely _denotes_ them. In Scheme, one may think of 'delay' as reify and 'force' as reflect. > But I'm not sure if Scheme and monadic style are a good fit for each > other. Using Haskell's type inference in conjunction with overloaded > monad operations and do-notation strikes me as an elegant approach. Yes, but so is Scheme. Let us consider running the following chain of MonadPlus: m1 >>= f1 >>= f2 >>= f3 >>= f4 Suppose, f1 did "fail". Haskell still has to execute the rest of >>= statements to propagate that exception till the end. In contrast, in Scheme, when we do shift, we literally skip over all remaining applications, till the closest (in the dynamic scope) reset. Monads in Haskell induce a separate, CPS-like, sublanguage. Bind, (>>=) denotes an application in that language. Because all terms in that language are CPSed, we get the sequential execution even if the host language is non-strict (Plotkin's indifference theorem). As Filinksi, and Moggi before him, observed, in a strict language with effects the language itself enforces the sequential discipline, so we do not need any extra contortions in the forms of explicit Monads.