[Haskell-cafe] (no subject)

Bertram Felgenhauer bertram.felgenhauer at googlemail.com
Sun Apr 24 21:20:24 UTC 2016


First off, sorry for the botched email earlier; I should know better
than to send an emails manually. (long story...)

Tom Ellis wrote:
> On Sun, Apr 24, 2016 at 08:07:40PM +0000, haskell-cafe-bounces at haskell.org wrote:
[snip]
> > David Feuer wrote:
> > > What I'm looking for is more limited than lazy IO or unsafeInterleaveIO,
> > > but it seems quite possible that there's no way to get just what I'm
> > > looking for with the IO type proper using GHC's implementation of IO. Lazy
> > > IO allows evaluation to drive action. When a thunk is forced, it may
> > > trigger I/O (spooky action at a distance). What I'm talking about is
> > > separating what actions are performed from what values are calculated from
> > > them. Here's a partial concept which won't actually compile because of the
> > > lazy pattern matches:
> > >
> > > data MyIO a = forall b . MyIO (b -> a) (IO b)
> > > instance Functor MyIO where
> > >    fmap f ~(MyIO t m) = MyIO (f . t) m
> > > instance Applicative MyIO where
> > >    pure a = MyIO (const a) (pure ())
> > >    MyIO t1 m1 <*> ~(MyIO t2 m2) =
> > >      MyIO (\(r1, r2) -> t1 r1 (t2 r2)) ((,) <$> m1 <*> m2)
> > > instance Monad MyIO where
> > >   ???
> > > instance MonadFix MyIO where
> > >   ???
> > 
> > I believe that using this interface `unsafeInterleaveIO` could be
> > implemented as follows, making it just as powerful as lazy IO:
> > 
> >     data Box a = Box a
> > 
> >     unsafeInterleaveMyIO :: MyIO a -> MyIO a
> >     unsafeInterleaveMyIO act = do
> >         act' <- Box `fmap` act
> >         return $ case act' of Box !r -> r
> > 
> > Have I missed anything?
> 
> Since MyIO and its associate functions don't contain any unsafe primitives
> it seems highly unlikely you can implement unsafeInterleaveIO with them!
> 
> In fact I can't see how MyIO is any different to IO.  All you can do with
> the function field is fmap it over the IO action field.

Note that the code for the Monad instance is missing. The desired
semantics as I understood them were that in `x >>= y`, `y` could access
the "data part" that is produced by the embedded function (first
component of MyIO) of `x` before the IO action associated with `x`
was performed; the IO action would be triggered when that function
forces its argument. This "early access" to the data part would then
allow `mfix` to be lazier than it currently is.

The point I'm trying to make is that these are exactly the semantics
that `unsafeInterleaveIO` provides, and to my mind this is best
demonstrated by implementing that function in the MyIO interface.

Cheers,

Bertram


More information about the Haskell-Cafe mailing list