I am trying to understand Haskell type variables for functions. I wrote a function:

```
applyTwice f x = f(f x)
```

I tried to understand the type variables for this function, so I did a `:t applyTwice`

. This is how Haskell interprets the types:

```
applyTwice :: (t -> t) -> t -> t
```

Then I created another function:

```
applyOnce f x = f x
```

This time for `:t`

Haskell returns

```
applyOnce :: (t1 -> t) -> t1 -> t
```

My questions are

How do we read/understand what these functions take and return?

This is for

`applyTwice`

. If they say anything left side of the`->`

is what the function takes and right hand side is what it returns then should it not be`applyTwice :: ((t -> t) -> t) -> t`

?`(t -> t)`

for`(f x)`

and`((t -> t) -> t)`

for`f (f x)`

and the return type being`t`

.- This is for
`applyOnce`

. Why is the function's type interpreted as`applyOnce :: (t1 -> t) -> t1 -> t`

? because we only take a function and return it's value. Should it not be`applyOnce :: (t1 -> t) -> t1`

?

As a beginner in Haskell I would like any advice in this.

We have:

```
applyTwice f x = f(f x)
```

This would make sense only if the types of `x`

and `f x`

were equivalent (else how would you be able to pass `f x`

to a function that takes `x`

?). Therefore, you could say that `applyTwice`

takes 2 input arguments:

- A function that takes a type t and returns the same type t
- An input of some type

Now this input could be of any type, say t1. But you also have to be able to apply the function to this input, and so the type of the input must also be t. Put together, we get the signature:

```
applyTwice :: (t -> t) -> t -> t
```

Remember that only the last term is the return type, and all others are types of the inputs.

Now consider:

```
applyOnce f x = f x
```

Simplistically, all it says about the function f is that it should be able to accept an input x of any type. There is nothing about what type the function should return **except** that `applyOnce`

should also return that same type. Hence, we end up with the signature you see:

```
applyOnce :: (t1 -> t) -> t1 -> t
```

where t1 could be any type and t could be any type (same or different from t1), but requiring that the return type of `f`

matches the return type of `applyOnce`

, represented by t here.

TL;DR: Your function signature for a function with n inputs will always have (n+1) terms, and the last term will be the return type of the function.

However, you should note that this is not actually how things work under the hood. All functions in Haskell actually take one argument i.e. they are *curried*. You can read more about this here.

### Return types

What arguments a function takes and what a function returns is quite a tricky question in Haskell, because of special stuff like partial application.

The `map`

function looks like it takes an `f :: a -> b`

, the transformation function and a list `xs :: [a]`

and returns a list of `ys :: [b]`

with each element of `xs`

transformed per `f`

. But `map`

can also be seen as a function which takes a simple function `f`

and returns *another* function, which acts upon lists and returns lists.

What I do to help me reason about arguments is first separate all types delimited by top level `->`

s. For example `map`

:

```
map :: (a -> b) -> [a] -> [b]
-- gives us
-- (a -> b) and [a] and [b]
```

The rightmost type is what is traditionally called the "return type" when map is called with all its arguments provided. The other types are the arguments I have to use, for example in the function definition.

Take this with a grain of salt, as you will see plenty of examples of definitions of functions which do not use all arguments explicitly to define the function.

Coming to your second question, you apparently mix up the arguments and the function body. Taking `applyTwice`

:

```
applyTwice f x = f (f x)
```

`f`

and `x`

are the arguments to `applyTwice`

and `f (f x)`

is the function body. Now `f`

must be a function, since it is applied to an argument `x`

. `x`

's type can be anything, let's call it `t`

. Now f must go from `t`

, the type of `x`

to something else, call it `s`

. But now `f x`

, which has type `s`

is an argument to `f`

again, so the compiler can deduce that `s ~ t`

. Now `f (f x)`

is again of type `s`

, which must be the same as `t`

, which means you end up with:

```
applyTwice :: (t -> t) -> t -> t
```

Analogously you can try this for `applyOnce`

and see that its type is `(t -> s) -> t -> s`

, which is just `$`

from the `Prelude`

.

Let's translate Haskell to English.

`applyTwice :: (t -> t) -> t -> t`

means that **applyTwice** accepts a function from a `t`

to a `t`

and a value `t`

and returns a `t`

. Indeed, if we look at the definition, we see that it applies a function `f`

to a value `x`

and feeds the result into `f`

once more. This implies - as indicated by the type signature - that `f`

and `f x`

must have the same type `t`

(since `f`

only accepts a `t`

as an argument).

In contrast, `applyOnce :: (t1 -> t) -> t1 -> t`

allows for `f x`

and `x`

to have different types (`t`

and `t1`

respectively), since this function doesn't feed the output of `f`

(of type `t`

) back into `f`

.

I think the confusion stems from the fact that you fail to distinguish between `f`

(the function) and `f x`

(the result of the function).

Lastly, the type you suggest for `applyOnce`

(namely `(t1 -> t) -> t`

) implies (nay *affirms*) that you can get the result of a function without providing an argument; remember that `(t1 -> t)`

is the input type (a function) and `t`

is the output type. How do you calculate `f(x)`

without an `x`

?

来源：https://stackoverflow.com/questions/42243902/haskell-function-type-clarification