
Kevin Jardine
Or is it possible to call a function in a monad and return a pure result? I think that is what the original poster was asking?
I know that unsafePerformIO can do this, but I thought that was a bit of a hack.
What most people forget is that in Haskell there is /no/ impure stuff involved. Even the IO monad is completely pure. The unsafePerformIO function breaks this rule, hence it's "unsafe". Take as an example the following toy implementation of the 'cat' program: main :: IO () main = do args <- getArgs case args of [] -> getContents >>= putStr files -> mapM_ (readFile >=> putStr) files Here the domain-specific language, which is defined by the IO monad, is used to model a computation, which interacts with the outside world. All of this code is completely pure. But the DSL models computations, which may change the world during (>>=). Even the 'putStr' function is well referentially transparent. You can safely replace its application by its result. But note that its result is /not/ of type (), but of type 'IO ()'. Its result is an IO computation, i.e. a statement in the DSL defined by IO. As a clarifying example look at this function: printAndSquare :: Integer -> IO Integer printAndSquare x = print x >> return (x^2) If you write 'printAndSquare 5' somewhere in your code, then you're calling the function 'printAndSquare' with the argument 5, which gives a result of type 'IO Integer'. You can safely replace any occurence of 'printAndSquare 5' by its result. The following four computations are equivalent: fmap read getLine >>= printAndSquare >>= print fmap read getLine >>= (\x -> print x >> return (x^2)) >>= print do num <- fmap read getLine square <- printAndSquare num print square do num <- fmap read getLine square <- print num >> return (num^2) print square I have made direct use of the referential transparency rule. The result of applying the function 'printAndSquare' is not the same as the run-time result of the computation, which it expresses. Everything between (>>=) is pure. You're dealing with normal Haskell expressions here, and there is no magic involved, since IO is really just a language. You never get "out of IO", because as soon as you do '<-' in do-notation, you are giving the result of an IO computation a certain name. Instead of saying getContents >>= putStr you say do content <- getContents putStr content The only difference is that you have named the result explicitly. Don't try to give this operational meaning. It's just a different way to express the same statement in the IO language. If you want to write a function, which returns a random boolean, the correct way to do it is one of these: randomBool :: RngState -> (Bool, RngState) randomBool :: State RngState Bool randomBool :: IO Bool In fact, the two latter examples aren't even functions. They are simply values -- statements in a domain-specific language. For the second example it's the 'State RngState' language, for the third example it's the IO language. The following is also simply a value: randomBool :: Bool But it's really a value of type Bool. It's not a statement in some DSL. It's not a computation. It's not a function. Just a constant value.
I'm still trying to understand how monads interact with types so I am interested in this as well.
A monad is a type constructor, which is an instance of the Monad class and which obeys the monad laws. That's it.
On Jul 30, 10:11 am, Kevin Jardine
wrote: Oops, I should have written
IO ByteString
as the State stuff is only *inside* execState.
But a monad none the less?
Kevin
On Jul 30, 9:59 am, Kevin Jardine
wrote: The original poster states that the type of modifiedImage is "simply ByteString" but given that it calls execState, is that possible?
Would it not be State ByteString?
Kevin
On Jul 30, 9:49 am, Anton van Straaten
wrote: C K Kashyap wrote:
In the code here - http://hpaste.org/fastcgi/hpaste.fcgi/view?id=28393#a28393 If I look at the type of modifiedImage, its simply ByteString - but isn't it actually getting into and back out of the state monad? I am of the understanding that once you into a monad, you cant get out of it? Is this breaking the "monad" scheme?
modifiedImage uses the execState function, which has the following type:
execState :: State s a -> s -> s
In other words, it applies a State monad value to a state, and returns a new state. Its entire purpose is to "run" the monad and obtain the resulting state.
A monadic value of type "State s a" is a kind of delayed computation that doesn't do anything until you apply it to a state, using a function like execState or evalState. Once you do that, the computation runs, the monad is "evaluated away", and a result is returned.
The issue about not being able to escape that (I think) you're referring to applies to the functions "within" that computation. A State monad computation typically consists of a chain of monadic functions of type (a -> State s b) composed using bind (>>=). A function in that composed chain has to return a monadic value, which constrains the ability of such a function to escape from the monad.
Within a monadic function, you may deal directly with states and non-monadic values, and you may run functions like evalState or execState which eliminate monads, but the function still has to return a monadic value in the end, e.g. using "return" to lift an ordinary value into the monad.
Anton _______________________________________________ Haskell-Cafe mailing list Haskell-C...@haskell.orghttp://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-C...@haskell.orghttp://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-C...@haskell.orghttp://www.haskell.org/mailman/listinfo/haskell-cafe
-- nightmare = unsafePerformIO (getWrongWife >>= sex) http://ertes.de/