Type of anonymous functions in Haskell - haskell

I have a problem with typing anonymous functions in Haskell. For example when we have:
\x -> x 5
The type checked in GHCI is Num t1 => (t1 -> t2) -> t2 while I was sure it is the opposite.Similarly type
\x -> a * x
is Num a => a -> a (I know we need to assume that a is an Integer as the type of (*) is Int -> Int -> Int (without typeclasses).
Another example would be
\f -> f x
And as far as I checked is sth like (a -> b) -> b
But I am totally concerned about typing anonymous function. What is the magic power to understand this? Maybe a way to rewrite this function to a "normal" one to see the type clearly?
SO MY QUESTION IS: How do we get these types? Where they come from and how to evaluate this?

>> How do we get these types ?
These types are what the Haskell system can deduce from the only thing it has, that is the definition given by the user, such as "x 5".
The important thing is not that the function is anonymous. It is that the function is not explicitely typed, so the Haskell system has to "guess" the type from the expression.
Prelude> let a=4
Prelude> :t \x -> a * x
\x -> a * x :: Num a => a -> a
Prelude>
Prelude> let f1 x = a*x
Prelude> :t f1
f1 :: Num a => a -> a
Prelude>
So, exactly same type for anonymous and named versions.
Of course, you can be more specific:
Prelude> let f4 :: Double -> Double ; f4 x = 4*x
Prelude> :t f4
f4 :: Double -> Double
Prelude>
Haskell does not force you to explicitly type everything.
It takes all explicit typing info (such as for f4), and implicit typing info produced by your definitions and your calls to library functions, as typing constraints.
If the constraints can be resolved unambiguously, fine; that's called type inference as mentioned by chi above. Otherwise, if the typing constraints are contradictory or ambiguous, execution aborts.

The following are three equivalent ways to write your first function:
f :: Num t1 => (t1 -> t2) -> t2
f = \x -> x 5
g :: Num t1 => (t1 -> t2) -> t2
g x = x 5
h :: Num t1 => (t1 -> t2) -> t2
h = ($ 5)
Note that this function, no matter which syntax you use in its definition, is a second-order function. That means that its argument, x, is itself a function. That is, x must have a type of the form x :: Constraint1 t1, Constraint2 t2 => t1 -> t2. More specifically, x must accept 5 as its first (and possibly only) argument. But that's the only inherent constraint on its argument. 5 :: Num t1 => t1, so x :: Num t1, Constraint2 t2 => t1 -> t2. There is no inherent constraint on the return value of x, so the most general (permissive) type is x :: Num t1 => t1 -> t2.
So that gives us the type for the argument of your function: \x -> x 5 :: Num t1 => (t1 -> t2) -> ?. But what about the return type? Well, your function just applies x to 5 and evaluates to (returns) the result, so your function returns the same type as x. Assuming your function can accept any possible function x, its type is thus \x -> x 5 :: Num t1 => (t1 -> t2) -> t2.
Note also that you can use any lowercase names you want, both for the parameter and the type variables. Thus you could just as well have written \function -> function 5 :: Num five => (five -> result) -> result.

I think you are complicating it in a way you don't have to. Basically when you have an anonymous function in Haskell and want to find type of it you need to find two types: first the one that is before -> symbol and then the type of whole expression on the right of the arrow ->. Base on your example:
\x -> x 5
We need to find the type of x which we know is a function that has one argument of some type belonging to the typeclass Num, and returns some unknown type - let's say t:
x :: Num a => a -> t
So x function returns something of type t:
x 5 :: t
And here's our answer:
\x -> x 5 :: Num a => (a -> t) -> t
The same situation is with the last one:
\f -> f x
f is again some function but this time we don't know the type of its argument
f :: a -> b
so a is type of x and the whole expression on the right returns b
f x :: b
And again - here it is, we have a type of the expression on the left of -> and on the right.
\f -> f x :: (a -> b) -> b

Related

Why `f x = x x` and `g x = x x x x x` have the same type

I'm playing with Rank-N-type and trying to type x x. But I find it counter intuitive that these two functions can be typed in the same way.
f :: (forall a b. a -> b) -> c
f x = x x
g :: (forall a b. a -> b) -> c
g x = x x x x x
I have also noticed that something like f x = x x ... x x (many xs) still has the same type.
Can anyone explain why it is the case?
The key is that x :: a -> b is a function that can provide a value of any type, no matter what argument is given. That means x can be applied to itself, and the result can be applied to x again, and so on and so on.
At least, that's what it promises the type checker it can do. The type checker isn't concerned about whether or not any such value exists, only that the types align. Neither f nor g can actually be called, because no such value of type a -> b exists (ignoring bottom and unsafeCoerce).
A simpler example
This is a phenomenon that can be observed whenever we use a variable which has a polymorphic type (like your x). The identity function id is perhaps the most famous example.
id :: forall a . a -> a
Here, all these expressions type check, and have type Int -> Int:
id :: Int -> Int
id id :: Int -> Int
id id id :: Int -> Int
id id id id :: Int -> Int
...
How is that possible? Well, the crux is that each time we write id we are actually meaning "the identity function on some unknown type a that should be inferred from the context". Crucially, each use of id has its own a.
Let's write id #T to mean the specific identity function on type T.
Writing
id :: Int -> Int
actually means
id #Int :: Int -> Int
which is straightforward. Instead, writing
id id :: Int -> Int
actually means
id #(Int -> Int) (id #Int) :: Int -> Int
where the first id now refers to the function space Int -> Int! And, of course,
id id id :: Int -> Int
means
(id #((Int -> Int) -> (Int -> Int))) (id #(Int -> Int)) (id #Int) :: Int -> Int
And so on. We do not realize that types get that messy since Haskell infers those for us.
The specific case
In your specific case,
g :: (forall a b. a -> b) -> c
g x = x x x x x
we can make that type check in many ways. A possible way is to define A ~ Int, B ~ Bool, T ~ (A -> B) and then infer:
g x = x #T #(T -> T -> T -> c) (x #A #B) (x #A #B) (x #A #B) (x #A #B)
I suggest to spend some time to realize that everything type checks. (Moreover our choices of A and B are completely arbitrary, and we could use any other types there. We could even use distinct As and Bs for each x, as long as the first x is suitably instantiated!)
It is then obvious that such inference is also possible even when x x x ... is a longer sequence.
This shouldn't really be any more surprising than the fact that
m :: (∀ a . a) -> (∀ a . a) -> (Int, Bool)
m p q = (p, q)
has the same type as
n :: (∀ a . a) -> (∀ a . a) -> (Int, Bool)
n p q = (q, p)
Much like in your example, this works because the universally-quantified argument can be used in lots of different way, with the compiler in each case choosing an appropriate type and enforcing x to act as having that type.
This is actually a rather contrived situation because types like ∀ a . a or ∀ a b . a->b are uninhabited (modulo ⊥), so you would never actually be able to use a RankN function with such an argument; pragmatically you wouldn't even write it either then!
Practically useful RankN functions usually impose some extra structure or typeclass constraint in their arguments, like
foo :: (∀ a . [a] -> [a]) -> ...
or
qua :: (∀ n . Num n => Int -> n -> n) -> ...

Can a type correct function be inapplicable? (Haskell)

I have a function foo = \f x -> let c = \y -> x in f c which I have type inferenced to find :
\forall a,b,r. ((b -> a) -> r) -> a -> r.
GHCI confirms this type: foo :: ((p1 -> p2) -> t) -> p2 -> t
However, I am unable to find an applicable function that meets these parameters such that foo evaluates.
I have tried the following functions with no success:
bu :: Num a => ([Char] -> a) -> a
bu x = (x "hello") * 2
ba :: (Fractional a1, Foldable t) => t a2 -> a1
ba x = (fromIntegral (length x) ) / 2
Another attempt was choosing the following functions:
bu :: Num a => ([Char] -> a) -> a -> a
bu x = (+ ((x "hello") * 2))
ba :: (Fractional a1, Foldable t) => t a2 -> a1
ba x = (fromIntegral (length x) ) / 2
Now I can call (bu ba) 4and get a correct result.
I understand why those don't work.
The issue seems to be that in the first arguement (p1 -> p2) -> t), t would need to be a function that takes the argument p2. However, as soon as we do that the type of that function changes to something like (a -> a) and can no longer be correctly consumed by foo.
This exercise has lead me to the question; can a function with a correct type be inapplicable?
My intuition leads me to believe that this is false and that an applicable input exists for any function with a valid type. Is there a proof for this?
Here is a simple proof that a function can be inapplicable (disregarding bottoms)
data Never = Never Never
justTryIt :: Never -> ()
justTryIt _ = ()
However your function IS applicable
main = print $ foo (\c -> c ()) 3
So what is the type of that lambda?
g :: (() -> a) -> a
g = \c -> c ()
Point is you don't need a function of
g :: (a -> b) -> c
Which is uninhabited (iGnOrInG bOtToMs). The type signature is just saying you can take a function where all 3 of those type (forall a b c.) can vary. IE this works equally as well
g :: (Int -> String) -> Bool
g f = null $ f 3
main = print $ foo g "so concrete"
A function of type p1 -> p2 is impossible to write; that basically says "given any possible type, I can give you any other possible type". Good luck with that!
The type (p1 -> p2) -> t is impossible for a similar reason. However, (p1 -> p2) -> Bool is quite possible:
f :: (p1 -> p2) -> Bool
f x = True
You can write similar functions for various choices of type t. (What you can't do is write a function that can somehow return any possible t out of nothing.)
More generally, can every implementable function be successfully called? That's an interesting question. I'm not sure what the answer is. I'd love to know!
EDIT: Thinking about it... the type signature of every implementable function can be interpreted as a theorum (and the implementation of the function is in some sense a "proof" of that theorum). A function that takes another function as input is like "this theorum is true if this other theorum is true". So if you can come up with a proof that "X is true if Y is true", where Y is definitely false... then you have your implementable function that can never be called.
All of this cheerfully ignores that real Haskell has several ways to break the type system and get around these nice results. For example, the function error "banana" has type a (i.e., any possible type). So in this "cheating" sense, all Haskell functions are callable.

Haskell function with type (num -> num) -> num

I am struggling with an exercise in R. Bird's functional programming book that asks for an example of a function with type (num -> num) -> num
The best I can come up with is a polymorphic type
func1 f = f 3
:t func1
func1 :: Num t1 => (t1 -> t2) -> t2
The problem I am having is that I can't specify the return type of f, so the type remains (num -> t2) -> t2.
My attempt to force the return type of f is as follows:
square x = x * x
:t func1 square
func1 square :: Num t2 => t2 -> t2
Because of course if I try to find the type of func1 ∘ square it will just be num -> num
If it is enough to give a function which can be assigned that type, then yours is already enough. That is, the following type-checks just fine:
func1 :: Num a => (a -> a) -> a
func1 f = f 3
If, on the other hand, you want a function which is inferred to have that type, then you need to do some trickery. What we want to do here is to specify that the result of f 3 and the 3 that we fed in have the same type. The standard way to force two terms to have the same type is to use asTypeOf, which is implemented this way:
asTypeOf :: a -> a -> a
asTypeOf x _ = x
So let's try:
> :t \f -> f 3 `asTypeOf` 3
(Num a, Num t) => (t -> a) -> a
Unfortunately for us, this doesn't work, because the 3 in f 3 and the standalone 3 are inferred to be using potentially different instances of Num. Still, it is a bit closer than \f -> f 3 was -- note the new Num a constraint on the output that we didn't have before. An obvious next idea is to let-bind a variable to 3 and reuse that variable as the argument to both f and asTypeOf; surely then GHC will get the picture that f's argument and result have the same type, right?
> :t \f -> let x = 3 in f x `asTypeOf` x
(Num a, Num t) => (t -> a) -> a
Drat. Turns out that lets do what's called "let generalization"; the x will be just as polymorphic as the 3 was, and can be specialized to different types at different use sites. Usually this is a nice feature, but because we're doing an unnatural exercise we need to do unnatural things...
Okay, next idea: some lambda calculi do not include a let, and when you need one, instead of writing let a = b in c, you write (\a -> c) b. This is especially interesting for us because Haskell uses a specially-restricted kind of polymorphism that means that inside c, the type of a is monomorphic. So:
> :t \f -> (\x -> f x `asTypeOf` x) 3
Num a => (a -> a) -> a
And now you complain that asTypeOf is cheating, because it uses a type declaration that doesn't match its inferred type, and the whole point of the exercise was to get the right type through inference alone. (If we were okay with using type declarations that don't match the inferred type, we could have stopped at func1 :: Num a => (a -> a) -> a; func1 f = f 3 from way back at the beginning!) Okay, no problem: there's another standardish way to force the types of two expressions to unify, namely, by putting them in a list together. So:
> :t \f -> (\x -> head [f x, x]) 3
Num a => (a -> a) -> a
Phew, now we're finally at a place where we could in principle build, from the ground up, all the tools needed to get a term of the right type without any type declarations.
func1 f = let x = f x in x This is a partial function, it technically has the type you want and you should be aware of what they are and how they work in haskell.

Comparing fmap type declaration to how it's used

I ran :t fmap (*) (Just 5) and got
fmap (*) (Just 5) :: Num a => Maybe (a -> a)
Type declaration of fmap says
fmap :: Functor f => (a -> b) -> f a -> f b
So am I right in thinking that (*) is being treated as (a -> (a -> a)) and corresponds to (a -> b) part of the fmap type declaration? If the (a -> a) part corresponds to b, why can't I do the following? And let the b represent the lambda function?
foo :: a -> b
foo x = (\y -> y + 3)
There's an implicit forall in your signature:
foo :: forall a b. a -> b
This means that your function must work for any a and b. Let's have a look at your function:
foo x = (\y -> y + 3)
Since x isn't restricted on the right hand side of =, it fulfils the requirements: it can be of any type. However, your right hand side has the following type:
ghci> :t (\y -> y + 3)
Num k => k -> k
Remember that your original function said that the choice of b can be arbitrary. However, your function's body restricts the return type to b ~ Num k => k -> k. You would have to use
foo :: Num b => a -> b -> b
By the way, foo's type already shows that you will not use the first argument, because there's no way to combine two values of different types in a general way. Indeed, one can proof that foo is const bar for some bar :: Num b => b -> b.
Exercises
Try to think of a function with type forall a b. a -> b.
In your initial example, a is constrained to be an instance of Num because of the 5 and the (*).
:type 5
5 :: Num a => a
:type (*)
(*) :: Num a => a -> a -> a
You are correct that the (a->a) gets unified with the b in the type of fmap.
:type (\y -> y + 3)
(\y -> y + 3) :: Num a => a -> a
Hence:
:type foo
foo :: Num a => t -> a -> a
As Willem Van Onsem says, b means "any type you like", not "any type that fits the invisible constraints I haven't mentioned".

Why function (+) matches type (a -> b -> b)?

fold function :
fold :: b -> (a -> b -> b) -> [a] -> b
fold z f [] = z
fold z f (x:xs) = f x (fold z f xs)
taken from http://www.seas.upenn.edu/~cis194/spring13/lectures/04-higher-order.html
Prelude> :t (+)
(+) :: Num a => a -> a -> a
*Main> fold (0) (+) [1,2,3]
6
What does type (a -> b -> b) match with type a -> a -> a for (+) function ?
As fold definition accepts function type (a -> b -> b) this means the first 2 parameters (a -> b) are required to be of different types ?
No, all it means is that a and b can be different, but it isn't mandatory for it to be different. In your case, it is the same.
A much simpler example to convey the point:
data SomeType a b = Test a b deriving (Show)
Now in ghci:
λ> :t Test
Test :: a -> b -> SomeType a b
λ> let x = Test (3 :: Int) (4 :: Int)
λ> :t x
x :: SomeType Int Int
You are thinking in reverse direction. You do not have to check whether + is identical or matches a -> b -> b, you want the type of + to be a specialization of a -> b -> b and to check this you have to unify the types.
Unification means that you want to see whether the type of + and the type a -> b -> b can be made equal by renaming the type variables.
So + has type Num x => x -> x -> x. Let's ignore the class constraint for now, and let's see if we can match the functional types.
The types become x -> x -> x and a -> b -> b. In fact it's better if we look at them as they really are, without using associativity: x -> (x -> x) and a -> (b -> b).
The -> is a type constructor. I.e. it is a function that maps a certain number of types to a different type. In this case the -> constructor maps two types t_1 and t_2 to the functional type (->) t_1 t_2 (which is usually denoted by t_1 -> t_2).
So the type x -> (x -> x) is actually (->) x ((->) x x) which is the type constructor -> applied to x and to the type constructor -> applied to x and x.
The other type is (->) a ((->) b b).
When unifying you consider the outermost type constructor for the two types (-> for both in this case). If this doesn't match, you cannot unify.
Otherwise you have to unify the arguments of the constructor.
So we have to unify x with a. They are both type variables, so we can rename one of them. Let's say that we rename a with x. So now we apply the renaming to the types, obtaining: (->) x ((->) x x) and (->) x ((->) b b) and you see that x and x now match.
Let's consider the second argument. It's not a type variable so we have to match the type constructor, and this is again -> for both. So we procede recursively on the arguments.
We want to match x and b. They are both type variables, so we can rename one of them. Say we rename x to b. We apply this substitution to the types, obtaining: (->) b ((->) b b) and (->) b ((->) b b). Now the everything matches. Hence the two types unify.
Regarding the class constraint, when we rename x with b we applied the substitution to the constraint too so Num x became Num b and the two final types are both Num b => b -> b -> b.
I hope this gave you some better understanding on how the types work and how the types are checked.
Side note: This is what haskell does when performing type inference. It first assign to an unknown function a fresh type variable t. Then it uses unification to obtain the type of the expression that defines it and check what type was associated with t, and this is the type of the function.

Resources