2 ms·
To add to lgas' point: The distinction between functions with side effects and descriptions of what IO will be done at run-time has many practical consequences
by saithound 6y ago
To add to lgas' point:
The distinction between functions with side effects and descriptions of what IO will be done at run-time has many practical consequences. For example, if you execute the Haskell code
greet name = do
putStrLn ("Hello, " ++ name)
repeat3 action = do
putStrLn "Doing it thrice."
action
action
action
putStrLn "Done it thrice."
main =
repeat3 (greet "themagicalcake")
you get the following output:
Doing it thrice.
Hello, themagicalcake
Hello, themagicalcake
Hello, themagicalcake
Done it thrice.
But if you execute the similar-looking Python script
def greet(name):
print ('Hello %s' % name)
def repeat3(action):
print ('Doing it thrice.')
action()
action()
action()
print ('Done it thrice.')
if __name__ == "__main__":
repeat3(greet('themagicalcake'))
you get
Hello themagicalcake
Doing it thrice.
Traceback (most recent call last):
File "test.py", line 10, in <module>
repeat3(greet('themagicalcake'))
File "test.py", line 5, in repeat3
action()
TypeError: 'NoneType' object is not callable
instead. The Haskell value `greet "themagicalcake"` has type `IO ()`: it is a value that describes IO to be done at runtime. In contrast, the Python value returned by the call `greet('themagicalcake')` has type `NoneType`, and this value does not describe anything. Calling `greet` itself had the side-effect of printing "Hello themagicalcake".
- kqr 6y ago...and the ability to treat I/O computations (these "descriptions" of I/O to perform) as plain values in the code is the reasons Haskell is sometimes affectionately known as "the best imperative language". It's not that you couldn't do the same thing in Python, it's that you get more fine and precise control over what happens by default in Haskell.
- lalos 6y agowould this work on python? repeat3(lambda: greet('themagicalcake'))
- saithound 6y agoIt would work in the sense that it would not throw an exception, but it wouldn't work the same way in every situation. Haskell's `greet "themagicalcake"` does not correspond to Python's `greet('themagicalcake')`, nor does it correspond to Python's `lambda: greet('themagicalcake')` in every situation. E.g. you can write main = greet "themagicalcake" in Haskell to get a program that just prints Hello themagicalcake but the Python program if __name__ == "__main__": lambda: repeat3(greet('themagicalcake')) prints nothing.