Re: Re: testing and the culture of Haskell

OK, so I get the idea that all functions are pure because they
just return actions.
So as I understand it now...
All functions are pure.
The evaluation of all functions not declared as IO results in no side effects.
The evaluation of all functions declared as IO may or may not have side effects.
But how can the function greetAdrian from the example below not be an IO
operation?
From: Maciej Piechotka
All Haskell functions are pure without exception. For example:
greet :: String -> IO () greet name = putStrLn $ "Hello, "++name
This is a pure function from String to IO (). This function (like all Haskell functions) has no side effects. Its return value of type IO () merely _represents_ an IO action. The runtime system knows how to act on this representation.
This also means that there is no such thing in Haskell as marking a function as side-effecting.
This distinction may be subtle, but it's important.
Steve
Steve,
Please could you clarify this for me since you are making exactly the opposite assertion than I have understood.
I am confused by you stating "All Haskell functions are pure without exception.".
Pure functions have no impact on 'anything'. They take input parameters (which they don't change) and return exactly the same result whenever the same input parameters are given.
greet :: String -> IO () greet name = putStrLn $ "Hello, "++name
This example you gave is not a pure function since it does have the side effect that the screen is changed by outputting the string "Hello, " and the name passed in.
greatAdrian :: String greetAdrian = let x = greet "Adrian" in x `seq` f x greet can be consider a pure function and value IO () is evaluated by seq. IO () represents an action(s) not execution of action(s). If f of x does not use any tricks nothing will be printed. IO a value it can be: - cast unsafely into a. However I guess we omit this shame for a moment - binded with other action. But the resultant type is now again IO b. So we still get a something - returned as main. Then we might consider whole Haskell program as metalanguage which returns single thing - other program. In similar way as: type PythonProgram = String main :: PythonProgram main = "print \"Hello World\"" is pure add_impure is pure. What we do with the result is other thing. Regards

When you put actions in a "do" block, what you are really doing under
the hood is using the ">>=" function to string actions together. (>>=)
:: m a -> (a -> m b) -> m b, so, when m ~ IO, (>>=) :: IO a -> (a ->
IO b) -> IO b. Thus, a do block of IO actions will itself be an IO
action. However, consider the function:
f :: IO a -> Int
f _ = 10
Now the value f (putStrLn "foo") is totally pure, and has the value of
10. A similar thing is going on with the greetAdrian function.
Hope that helps.
Alex
On Fri, Jan 22, 2010 at 7:34 PM, Adrian Adshead
OK, so I get the idea that all functions are pure because they just return actions.
So as I understand it now...
All functions are pure. The evaluation of all functions not declared as IO results in no side effects. The evaluation of all functions declared as IO may or may not have side effects.
But how can the function greetAdrian from the example below not be an IO operation?
From: Maciej Piechotka
Subject: Re: Re: testing and the culture of Haskell Newsgroups: gmane.comp.lang.haskell.beginners Date: 2010-01-23 00:31:42 GMT (2 hours and 52 minutes ago) On Fri, 2010-01-22 at 20:59 +0000, Adrian Adshead wrote:
All Haskell functions are pure without exception. For example:
greet :: String -> IO () greet name = putStrLn $ "Hello, "++name
This is a pure function from String to IO (). This function (like all Haskell functions) has no side effects. Its return value of type IO () merely _represents_ an IO action. The runtime system knows how to act on this representation.
This also means that there is no such thing in Haskell as marking a function as side-effecting.
This distinction may be subtle, but it's important.
Steve
Steve,
Please could you clarify this for me since you are making exactly the opposite assertion than I have understood.
I am confused by you stating "All Haskell functions are pure without exception.".
Pure functions have no impact on 'anything'. They take input parameters (which they don't change) and return exactly the same result whenever the same input parameters are given.
greet :: String -> IO () greet name = putStrLn $ "Hello, "++name
This example you gave is not a pure function since it does have the side effect that the screen is changed by outputting the string "Hello, " and the name passed in.
greatAdrian :: String greetAdrian = let x = greet "Adrian" in x `seq` f x
greet can be consider a pure function and value IO () is evaluated by seq. IO () represents an action(s) not execution of action(s). If f of x does not use any tricks nothing will be printed.
IO a value it can be: - cast unsafely into a. However I guess we omit this shame for a moment - binded with other action. But the resultant type is now again IO b. So we still get a something - returned as main. Then we might consider whole Haskell program as metalanguage which returns single thing - other program. In similar way as:
type PythonProgram = String main :: PythonProgram main = "print \"Hello World\""
is pure add_impure is pure. What we do with the result is other thing.
Regards
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

Hi Alex,
That does help, but raises a further question.
If (>>=) :: m a -> (a -> m b) -> m b
Then whenever the IO monad is entered it can not be escaped,
so in the example you gave:-
f :: IO a -> Int
f _ = 10
while f (putStrLn "foo") is a pure function evaluating to 10,
neither the IO Action, nor the a (from 'IO a') can be used without
using the (>>=) or (>>). Therefore since the parameter can not
be used in the function f without entering the IO monad, your
function would be equivalent to :-
f :: Int
f = 10
I have two questions to try and clarify my understanding.
1) Is it possible to have a function with an IO Action as an input
parameter (and not just ignore the parameter) and have a non-IO
return value?
(ie is f :: IO a -> b possible without ignoring the IO a)
2) Is it possible to have a function which evaluates any IO Action
within the body and have a non-IO return value?
(ie is f :: a -> b possible while evaluating any IO Action
within the body.)
My understanding of Haskell was that both of these situations
would not be possible, and the return value would always be
of the form IO b. (For these questions I am excluding use of
unsafePerformIO)
Many thanks for your time.
Adrian.
--- On Sat, 23/1/10, Alexander Dunlap
OK, so I get the idea that all functions are pure because they just return actions.
So as I understand it now...
All functions are pure. The evaluation of all functions not declared as IO results in no side effects. The evaluation of all functions declared as IO may or may not have side effects.
But how can the function greetAdrian from the example below not be an IO operation?
From: Maciej Piechotka
Subject: Re: Re: testing and the culture of Haskell Newsgroups: gmane.comp.lang.haskell.beginners Date: 2010-01-23 00:31:42 GMT (2 hours and 52 minutes ago) On Fri, 2010-01-22 at 20:59 +0000, Adrian Adshead wrote:
All Haskell functions are pure without exception. For example:
greet :: String -> IO () greet name = putStrLn $ "Hello, "++name
This is a pure function from String to IO (). This function (like all Haskell functions) has no side effects. Its return value of type IO () merely _represents_ an IO action. The runtime system knows how to act on this representation.
This also means that there is no such thing in Haskell as marking a function as side-effecting.
This distinction may be subtle, but it's important.
Steve
Steve,
Please could you clarify this for me since you are making exactly the opposite assertion than I have understood.
I am confused by you stating "All Haskell functions are pure without exception.".
Pure functions have no impact on 'anything'. They take input parameters (which they don't change) and return exactly the same result whenever the same input parameters are given.
greet :: String -> IO () greet name = putStrLn $ "Hello, "++name
This example you gave is not a pure function since it does have the side effect that the screen is changed by outputting the string "Hello, " and the name passed in.
greatAdrian :: String greetAdrian = let x = greet "Adrian" in x `seq` f x
greet can be consider a pure function and value IO () is evaluated by seq. IO () represents an action(s) not execution of action(s). If f of x does not use any tricks nothing will be printed.
IO a value it can be: - cast unsafely into a. However I guess we omit this shame for a moment - binded with other action. But the resultant type is now again IO b. So we still get a something - returned as main. Then we might consider whole Haskell program as metalanguage which returns single thing - other program. In similar way as:
type PythonProgram = String main :: PythonProgram main = "print \"Hello World\""
is pure add_impure is pure. What we do with the result is other thing.
Regards
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

Am Samstag 23 Januar 2010 21:31:47 schrieb Adrian Adshead:
Hi Alex,
That does help, but raises a further question.
If (>>=) :: m a -> (a -> m b) -> m b
Then whenever the IO monad is entered it can not be escaped, so in the example you gave:-
f :: IO a -> Int f _ = 10
while f (putStrLn "foo") is a pure function evaluating to 10, neither the IO Action, nor the a (from 'IO a') can be used without using the (>>=) or (>>). Therefore since the parameter can not be used in the function f without entering the IO monad, your function would be equivalent to :-
f :: Int f = 10
Rather to const 10 except with a restricted type.
I have two questions to try and clarify my understanding.
1) Is it possible to have a function with an IO Action as an input parameter (and not just ignore the parameter) and have a non-IO return value? (ie is f :: IO a -> b possible without ignoring the IO a)
Excluding unsafePerformIO, only in a very weak sense. ioseq :: IO a -> b -> b ioseq ioa b = ioa `seq` b doesn't quite ignore the parameter, but apart from that, I only see rustyBallpointTracheotomy (Kydos to Brent Yorgey for that :).
2) Is it possible to have a function which evaluates any IO Action within the body and have a non-IO return value? (ie is f :: a -> b possible while evaluating any IO Action within the body.)
Assuming by evaluating you mean executing and not (return 5 >> return 6) ~> IO (\s -> (s,6)) , no, that's not possible.
My understanding of Haskell was that both of these situations would not be possible, and the return value would always be of the form IO b. (For these questions I am excluding use of unsafePerformIO)
Many thanks for your time.
Adrian.

On Jan 23, 2010, at 16:08 , Daniel Fischer wrote:
Am Samstag 23 Januar 2010 21:31:47 schrieb Adrian Adshead:
I have two questions to try and clarify my understanding.
1) Is it possible to have a function with an IO Action as an input parameter (and not just ignore the parameter) and have a non-IO return value? (ie is f :: IO a -> b possible without ignoring the IO a)
Excluding unsafePerformIO, only in a very weak sense.
And, while you could do the dance to make unsafePerformIO available and use it, the aggressive optimizations the compiler makes on pure code can lead to extremely unexpected results.
2) Is it possible to have a function which evaluates any IO Action within the body and have a non-IO return value? (ie is f :: a -> b possible while evaluating any IO Action within the body.)
Assuming by evaluating you mean executing and not
(return 5 >> return 6) ~> IO (\s -> (s,6))
, no, that's not possible.
Again, barring unsafePerformIO, and that will bite you if you use it without knowing exactly what you're doing and why and *forcing* the compiler to agree with you. (As it turns out, you can often figure out the implementation details of your chosen compiler's IO and force the issue. But any code that do so *is* reimplementing unsafePerformIO, and you will pay dearly.) -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH

On Jan 23, 2010, at 15:31 , Adrian Adshead wrote:
If (>>=) :: m a -> (a -> m b) -> m b
Then whenever the IO monad is entered it can not be escaped, so in the example you gave:-
f :: IO a -> Int f _ = 10
while f (putStrLn "foo") is a pure function evaluating to 10, neither the IO Action, nor the a (from 'IO a') can be used without using the (>>=) or (>>). Therefore since the parameter can not
False; you could feed anything an IO value that doesn't otherwise reject it; the definitions of (>>) and (>>=) don't constrain where you can use an (IO a), they specify that if you use (>>) or (>>=) then you can't discard the (Monad m) context. Since the only thing a function that takes a completely unconstrained type (a) can do is pass it through unchanged or discard the value (think about it), and the result of the main function must be (IO a), *that* limits what you can do with an (IO a). You can pass it on (id), discard it (const, or the fancier versions of const that have been discussed in this thread), or feed it using (>>) or (>>=) to something else expecting an (IO a), or to anything else that will likewise preserve the IO encapsulation. Control.Applicative and Control.Arrow are other mechanisms that do so; IO has an Applicative instance, and any Monad has an Arrow (Kleisli m)) instance. Since Haskell's type system is open, it's never possible to rule out other qualifying instances. -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH

Adrian Adshead wrote:
1) Is it possible to have a function with an IO Action as an input parameter (and not just ignore the parameter) and have a non-IO return value? (ie is f :: IO a -> b possible without ignoring the IO a)
pretty much no, but consider, we can return a data structure constructed out of those IOs, without actually learning anything about what actions they are intended to do. For example: f :: IO a -> [IO a] f io = iterate (\io2 -> (io2 >> io2)) io returns a list, in which the first action would do the IO once, the second would do it twice, the third element would do it four times, the fourth element, eight times, and so forth. Obviously, it is only occasionally useful to do something strange like that. -Isaac
participants (5)
-
Adrian Adshead
-
Alexander Dunlap
-
Brandon S. Allbery KF8NH
-
Daniel Fischer
-
Isaac Dupree