[Haskell-cafe] The values of infinite lists
Paul Hudak
paul.hudak at yale.edu
Tue May 23 00:41:03 EDT 2006
Brian Hulley wrote:
> Therefore I humbly submit a call for authors of books/tutorials on IO to
> come clean and admit the fact that IO completely changes the language
> from being purely functional into a functional + process calculus
> language :-)
As an author of such a book, I'm not willing to do this. Or at least,
if we omit concurrency and impure operations such as unsafePerformIO,
Haskell is a purely functional, sequential, and deterministic language,
whose semantics, including that of IO, can be explained via conventional
equational reasoning. I'm sure that it can also be explained via a
suitable process calculus, but that is an overkill -- such calculi are
best used for describing non-deterministic / concurrent languages.
-Paul
Brian Hulley wrote:
> Robert Dockins wrote:
>
>> On Wednesday 10 May 2006 02:49 pm, you wrote:
>>
>>> I could write:
>>>
>>> ] (r',_) = runIO (mapM print ones) realWorld
>>>
>>> and this computation, even though some printing would be observable,
>>> still evaluates to bottom, because r' will never be bound.
>>
>>
>> Humm... how do you define observable? If r' is never bound, how can I
>> observe any intermediate printing?
>
>
> I meant observable in the sense that the printing is just like a debug
> trace of evaluation, and so is irrelevant when using the world-state
> transformer point of view.
>
>> [snip]
>> The world-state-transformer idea is nice as a didactic tool, but I
>> don't think its the right world-view for serious thinking about
>> Haskell's semantics.
>>
>>>
>>> I thought everything in Haskell is purely functional - surely that
>>> is the whole point of using monads? :-)
>>
>>
>> Sure. But in that world-view then you don't think of the IO actions
>> as "running" at all, so you can't discuss their termination
>> properties. This is more or less what all accounts (at least the
>> ones I've seen) of Haskell's semantics do -- they provide a
>> denotational semantics for the lambda terms basicaly ignore the
>> meaning of IO actions.
>
>
> I think from the world-state transformer pont of view, all
> non-terminating computations must be seen as evaluating to _|_, but as
> you point out, this point of view isn't that useful in practice.
>
>> My favorite view of Haskell semantics is of a coroutining abstract
>> machine which alternates between evaluating lambda terms to obtain
>> the terms of a process calculus, and then reducing those process
>> calculus terms; some process calculus reduction rules call into the
>> lambda reduction engine to grow more (process calculus) terms to
>> reduce. The observable behavior of the program is defined in terms
>> of the sequence of reductions undertaken by the process calculus
>> engine.
>>
>> In this view "bottom" is the denotion of all (lambda) terms which
>> make the lambda portion of the machine fail to terminate, and never
>> return control to the process calculus part -- thus no further
>> observations will be generated by the program.
>
>
> Thanks for pointing out the process calculi. I found a good page about
> them at http://en.wikipedia.org/wiki/Process_calculus
>
> It would be good if there was a more detailed description of Haskell
> semantics along the lines of what you've said above, so that it would be
> clear that the running of an IO action is something very different from
> the running of other monads. (Not too mathematical a description but a
> tutorial style description)
>
> As I understand it, the IO monad shares with other monads the fact that
> first a composite action is built from primitive actions using >>= and
> return etc, and this composition is purely functional, even though >>=
> and return are special built-in functions for the IO monad. (As an
> aside, I must point out that the word "do" is ultra confusing in this
> respect, because "do" does not actually run the action, it is just
> syntactic sugar for composing actions which might be "done" later.)
>
> Then, in contrast to all other monadic actions, which are "run" by
> simply evaluating something hidden inside them (eg applying a function
> hidden inside the monad to some initial state), the running of an IO
> action involves the quite complicated interaction you've described
> above, and really does go outside the functional realm.
>
> The problem with the RealWorld view of IO, is that it is quite wrong,
> yet this is the view propounded everywhere, so that anyone who thinks
> there is something complicated about IO assumes it is because they
> themselves haven't understood something properly since books/tutorials
> keep saying how simple and purely functional it all is! ;-)
>
> (Just like in primary school when teachers make out associativity and
> commutivity of addition/multiplication are trivial thus leading
> countless would-be mathematicians who immediately see these are
> complicated but think this is their fault alone, to abandon all hope ;-))
>
> Therefore I humbly submit a call for authors of books/tutorials on IO to
> come clean and admit the fact that IO completely changes the language
> from being purely functional into a functional + process calculus
> language :-)
>
> Best regards, Brian.
More information about the Haskell-Cafe
mailing list