## Friday, January 18, 2008

### Haskell Function calls and Parentheses

As you may have noticed, passing input to a function in haskell is simple because of the statically type nature of the language. A function can have a complicated input and output return, but at least you are given the parameters of that particular function. In python you can pass anything to a function; you can pass a function, a integer constant, an instance of a class and yet the function really only expects an boolean.

[2.] Examples

putStrLn :: String -> IO ()

For example, putStrLn expects a string as an input and will return unit in the IO Monad.

>putStrLn "abc"

Will print abc to the console.

Prelude> putStrLn "abc" ++ "123"
`:1:0:    Couldn't match expected type `[a]' against inferred type `IO ()'    In the first argument of `(++)', namely `putStrLn "abc"'    In the expression: putStrLn "abc" ++ "123"    In the definition of `it': it = putStrLn "abc" ++ "123"Prelude>`

The following example gave an error. Why? We gave putStrLn three arguments as opposed to the one. Here are the extra arguments, "++" and "123".

To fix the issue:

putStrLn ("abc" ++ "23")

Or even:

(putStrLn ("abc" ++ "23"))

[3.] Dollar Sign, syntatic sugar

We can also use the syntatic sugar, the dollar sign function to alleviate us from having to wrap the arguments in parentheses. Here is the type:
`Prelude] :type (\$)(\$) :: (a -> b) -> a -> b`

Pass (\$) The infix function has a first input parameter (a -> b), a function and then the 'a' argument which will output b. The following code demonstrates three different calls to putStrLn, but the final output is the same.
`Prelude] putStrLn "abc"abcPrelude] putStrLn \$ "abc"abcPrelude] (putStrLn "abc")abcPrelude]`

Here is another working example:

putStrLn \$ "abc: " ++ show(3) ++ show(4)

(\$) :: (a -> b) -> a -> b

putStrLn represents this part of the input (a -> b)
'a' represents the String input and b represents the output of putStrLn String which is the IO () monad.

For this aspect of the call, "abc: " ++ show(3) ++ show(4);

The (++) operator has the following type definition:

Prelude> :t (++)
(++) :: [a] -> [a] -> [a]

Where [a] can be represented by [Char].

Here are another set of working examples.
`Prelude> putStrLn \$ "abc: " ++ (show(3) ++ show(4))abc: 34Prelude> putStrLn \$ ("abc: " ++ (show(3) ++ show(4)))abc: 34Prelude> (putStrLn \$ ("abc: " ++ (show(3) ++ show(4))))abc: 34Prelude> (putStrLn \$ ("abc: " ++ (show(3) ++ show(4))))abc: 34Prelude> (putStrLn ("abc: " ++ (show(3) ++ show(4))))abc: 34`

Those examples are a little confusing because the (++) operator calls are resulting to one "string" input. For example:

let z = "abc: " ++ show(3) ++ show(4)

Is of type String.

[4.] Function composition

The infix dot operator shown below takes one function, another function and an input and returns the output c.
`Prelude] :t (.)(.) :: (b -> c) -> (a -> b) -> a -> c`

If we used the putStrLn function, and show function; what combinations could we come up with?

Note, show is defined by the following signature.
`Prelude] :t showshow :: (Show a) => a -> String`

`Prelude] putStrLn . show \$ 55Prelude]`

I will use the following notation to denote the operation invoked above:

### Function: **putStrLn** ||| Type: ( String -> IO () ) ###
infix dot-operator and then:
### Function: **show** ||| Type: ( a -> String ) ###
infix dollar sign operator and then the value of 5.
`Prelude] putStrLn . show \$ 55Prelude]`

The following calls also worked
`Prelude> putStrLn \$ show 55Prelude> putStrLn (show \$ 5)5Prelude> putStrLn \$ (show \$ 5)5Prelude> (putStrLn \$ (show \$ 5))5`

If you are given a list and need to print each element on its own line, you can use the following snippet.
`mapM_ (\x -> (putStrLn ("Token: " ++ x ++ " Len: " ++ (show (length x))))) ["ab", "1231", "ddd"]`

Do two things to make function composition look easier, think backwards and consider that putStrLn, show and (\$) are operations with only one input and one output. As you can see, with haskell are many different ways to do something as simple as invoke a function.

edited: Apparently, I got so carried away, I didn't acknowledge that you can just call the function without any operators. E.g; [ putStrLn \$ show 5 ] Sorry if that simple fact wasn't made clear.

Anonymous said...

Prelude> putStrLn "abc" ++ "123"

Actually, the issue is precedence, not of too many arguments (in fact, (++) can't be passed as an argument like that). Functions have higher precedence than operators, so that expression is evaluated as:

(putStrLn "abc") ++ "123"

And that's indeed exactly what the error message is saying, isn't it? : )

Anonymous said...

(putStrLn ("abc" ++ "23"))

Also, while there's nothing wrong with that, I think it's really unnecessary. I learned Lisp first, and I remember I would do the same thing too. But in Haskell, that would be equivalent to writing, say:

x = (1)

[But as you know, one situation where that's necessary is for negative numbers.]