5 ms·
Short answer: No, you can't. Long answer: You can, but Haskell is very serious about keeping pure code separate from impure code. Any function which performs I
by argv_empty 13y ago
Short answer: No, you can't.
Long answer: You can, but Haskell is very serious about keeping pure code separate from impure code. Any function which performs I/O is impure, so its output must be an IO Thing instead of just a Thing. This means anything that uses its output must accept an IO Thing instead of an ordinary Thing, and so on. Of course, the way I/O works means that a 'Type1 -> Type2' function into can be transformed into an 'IO Type1 -> IO Type2' or a 'Type1 -> IO Type2' function (this applies to many things other than I/O -- consult one of the many monad tutorials for more on that). Haskell even includes some special syntax for invoking these transformations that makes things look rather like an imperative language, but adding in a debug print still requires you to rewrite a lot more code than you would have to in another language. Alternatively, you could use unsafePerformIO (whose type is 'IO a -> a') to hide from the type system the fact that you've done some I/O, but you may run into trouble with the printing not behaving as you expect (due to Haskell's lazy evaluation).
- dllthomas 13y agoYour long answer is correct. I think I disagree with your short answer. You can, and this is not just a technicality - it can be useful in debugging. It's certainly true that laziness means that when things print will be unintuitive if your intuition is trained on strict languages, so any short answer conveying as little information as just "yes" or "no" is liable to be confusing, though...
- kyllo 13y agoWhoa, really? You have to use a monad just to print text to stdout in Haskell?
- PeterisP 13y agoThe concept is that affecting stdout isn't "just" - it requires a clear definition when (and if) that function will be executed, and in Haskell you don't do that if you can avoid that - it allows for lazy execution, actually running the function less (or 0) times depending on how it's result is used. I.e., if your program needs top 3 results in a race, then you can safely use a function that returns all the results, but since you afterwards use only first three then the remainder aren't calculated, that code most likely isn't run and the order of any "embedded" print statements would be undefined. That being said, standard Debug.Trace module allows simple adding of debug prints anywhere.
- dllthomas 13y agoRemember that Haskell is lazy. In broad strokes, the way you control when things happen is to sequence them by combining them (directly or indirectly) into the massive IO action that becomes main. If you don't care when it happens, you can use unsafePerformIO - which is just fine for debugging, though there are often better approaches.