[Haskell-cafe] Is it possible to make lazy combinators for IO?

David Feuer david.feuer at gmail.com
Mon Apr 18 23:25:30 UTC 2016


lazyMap :: (a -> b) -> IO a -> IO b, hypothetically.

Let me take a step back. There are two ways I know of to use the result of
an IO action. The most common way, by far, is to use >>= to send it on to
the next computation. The other notable way is to use fixIO.

No part of the result of an IO action becomes available until that action
"completes" (in the shady case of lazy IO, this may be immediate, but I'm
ignoring lazy IO for this discussion). This causes the well-known
inefficiency of mapM in IO: individual results cannot be consed until the
entire computation is complete. It seems to cause much more painful effects
for fixIO--lazy programming techniques may simply be unavailable.

For example, it's possible for a pure computation using a queue in a
single-threaded fashion to represent that queue as a list, tying the knot
to pass the list of all enqueued elements to the beginning. If an IO
computation wants to use a queue, this technique does not seem to be
available. The knot can be tied with fixIO, but conses are delayed until
it's too late--attempting to dequeue an element will block forever.

I'm wondering if there's some way to make this sort of thing work, either
with plain Haskell IO or some thin layer built on top.
On Apr 18, 2016 5:12 PM, "David Turner" <dct25-561bs at mythic-beasts.com>
wrote:

> Sorry, you've lost me. I suspect you're trying to give a minimal example
> of the problem you're having, but you've stripped away too much context.
> What are lazyMap and f? At least, what are their types?
> On 18 Apr 2016 22:03, "David Feuer" <david.feuer at gmail.com> wrote:
>
>> Consider the implementation of `second` for pairs:
>>
>> second f ~(a,b) = (a, f b)
>>
>> Now
>>
>> fix $ second (3 :)
>>
>> Will be (undefined, [3,3,....])
>>
>> Translating this to IO, I'd want
>>
>> lazyMap f undefined
>>
>> to produce as much as possible of the result, although it cannot produce
>> the final State# RealWorld token.
>> On Apr 18, 2016 4:47 PM, "David Turner" <dct25-561bs at mythic-beasts.com>
>> wrote:
>>
>>> You can't know that the final result of the computation (x `seq`
>>> (3:...)) will begin with 3, because sometimes it doesn't! More
>>> specifically, it diverges (without yielding the 3) if x diverges.
>>>
>>> I don't think this is anything special about mfix: (let x = x `seq`
>>> 3:... in x) also diverges for the same reason.
>>>
>>> Hope that helps,
>>>
>>> David
>>> On 18 Apr 2016 21:19, "David Feuer" <david.feuer at gmail.com> wrote:
>>>
>>>> If
>>>>
>>>> f :: a -> IO a
>>>>
>>>> for some a, and I want to use
>>>>
>>>> mfix f
>>>>
>>>> then f must not inspect its argument in any way, or the computation
>>>> will get stuck. In some cases, this seems a bit harsh. For example,
>>>>
>>>> mfix (\x -> fmap (3 :) (x `seq` readLn))
>>>>
>>>> looks perfectly reasonable. There is no need to inspect the return []
>>>> action to know that the final result of the computation will begin
>>>> with 3:. Is there a lazy IO mapping function somewhere that can work
>>>> such magic?
>>>> _______________________________________________
>>>> Haskell-Cafe mailing list
>>>> Haskell-Cafe at haskell.org
>>>> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>>>>
>>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20160418/01c860f3/attachment-0001.html>


More information about the Haskell-Cafe mailing list