Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I print 2 elements with putStr Haskell?

I'm new to Haskell and I am wondering how can I print the results of two functions in Haskell, something I would do in c++ like:

cout << f() << g();

Or in c#:

Console.WriteLine(f() + " " + g());

In Haskell I tried something like

main =
    --putStr ( show $ square 3 )
    putStr ( show $ fibSeries 12 ) 

square :: Int -> Int
square x = x * x

fib :: Int -> Int
fib 0 = 0
fib 1 = 1
fib n = fib (n - 1) + fib (n - 2)

fibSeries :: Int -> [Int]
fibSeries x = map fib [0..x]

but I had to comment the first command because it has given me a compile-time error.

The error is:

src\Main.hs:21:5:
    Couldn't match expected type `(String -> IO ()) -> String -> t0'
                with actual type `IO ()'
    The function `putStr' is applied to three arguments,
    but its type `String -> IO ()' has only one
    In the expression:
      putStr (show $ square 3) putStr (show $ fibSeries 12)
    In an equation for `main':
        main = putStr (show $ square 3) putStr (show $ fibSeries 12)
like image 981
Thanatos Avatar asked Jun 24 '13 08:06

Thanatos


1 Answers

tl;dr You're so close!

main = do
    putStr ( show $ square 3 )
    putStr ( show $ fibSeries 12 )

Note that this won't put in any whitespace, you may wish to insert putStr " ".


Here's what's going on: Haskell's main part, the purely functional language, doesn't have any such thing as "order of computation / action". If you write two lines with statements like print 5, they're just parsed as one line, namely

print 5 print 5

which means the following: print is a function that takes the arguments 5, print, and 5, and returns the type of main (an IO action). So the type would need to be something like

type PrintType = Int -> PrintType -> Int -> IO()

which is of course nonsense. To tell Haskell you actually want to sequence a chain of actions (what you do all the time in imperative languages, but need much more seldom in functional programming), we have this nice do notation, which works a lot (but not always quite!) like you'd expect from an imperative standpoint.

To understand how that really works, you need to learn about monads. Those are explained in any decent Haskell tutorial. Read LYAH or something.


Further notes on your code: there's not much point in doing such a printing job sequentially, really. You can just produce a string with all the information you want, and then print that in one go:

main = putStrLn $ show (square 3) ++ " " ++ show (fibSeries 12)

or, if you're not so much interested in formatting but just in getting the information,

main = print ( square 3, fibSeries 12 )

which will result in the output (9,[0,1,1,2,3,5,8,13,21,34,55,89,144]).

like image 130
leftaroundabout Avatar answered Oct 10 '22 06:10

leftaroundabout