haskell-cafe@haskell.org
[Top] [All Lists]

Re: [Haskell-cafe] Fighting the monad stack, MonadIO

Subject: Re: [Haskell-cafe] Fighting the monad stack, MonadIO
From: "Ryan Ingram"
Date: Thu, 10 Apr 2008 18:06:18 -0700
On 4/10/08, Adam Smyczek <adam.smyczek@xxxxxxxxx> wrote:
> If yes, is this a general concept/pattern
> how to hide functionality of a underlying monad,
> in this case hide IO entirely?

Yes, that's correct, although with IO you can't hide it entirely;
eventually you need a way to actually run the computation, and if
that's built on IO there's no way to do that without at least a way to
get -back- to the IO Monad.

On the other hand, you can use this to encapsulate "sandboxed" computations:

> module Console (Console, execConsole, consoleGetLine, consolePutLine)
> where

> newtype Console a = MkConsole { execConsole :: IO a }
>   deriving (Monad, Functor)

> consoleGetLine :: Console String
> consoleGetLine = MkConsole getLine

> consolePutLine :: String -> Console ()
> consolePutLine = MkConsole . putStrLn

MkConsole is a private constructor not exported from this module, so
the only way to construct one is via the operations we provide and the
monad/functor operations.  So we can prove that these operations never
do any network access, or file I/O, or weird pointer access.

Of course, with unsafeCoerce# and/or unsafePerformIO, client code can
break either/both of these claims:

> runConsole :: Console a -> a
> runConsole = unsafePerformIO . execConsole

> instance MonadIO Console where
>    liftIO = unsafeCoerce#
>    -- works because newtype is guaranteed not to change
>    -- the runtime representation

  -- ryan
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@xxxxxxxxxxx
http://www.haskell.org/mailman/listinfo/haskell-cafe

<Prev in Thread] Current Thread [Next in Thread>