Haskell Function calls and Parentheses

[1.] Function Calls in Haskell

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"
abc
Prelude] putStrLn $ "abc"
abc
Prelude] (putStrLn "abc")
abc
Prelude]

Here is another working example:

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

If we return to the ($) definition and putStrLn.
($) :: (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: 34
Prelude> putStrLn $ ("abc: " ++ (show(3) ++ show(4)))
abc: 34
Prelude> (putStrLn $ ("abc: " ++ (show(3) ++ show(4))))
abc: 34
Prelude> (putStrLn $ ("abc: " ++ (show(3) ++ show(4))))
abc: 34
Prelude> (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 show
show :: (Show a) => a -> String


Prelude] putStrLn . show $ 5
5
Prelude]

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 $ 5
5
Prelude]

The following calls also worked

Prelude> putStrLn $ show 5
5
Prelude> putStrLn (show $ 5)
5
Prelude> putStrLn $ (show $ 5)
5
Prelude> (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.

Comments

Popular posts from this blog

Is Java the new COBOL? Yes. What does that mean, exactly? (Part 1)

On Unit Testing, Java TDD for developers to write

JVM Notebook: Basic Clojure, Java and JVM Language performance