Two functions seem equal but different in Haskell - haskell

I'm trying to implement boolean without Prelude in Haskell.
When expression, beq true true "TRUE" "FALSE" is evaluated, it's okay. But when I try to evaluate beq' true true "TRUE" "FALSE", it fails by some difference between expected type and actual type.
This is the code.
import qualified Prelude as P
i = \x -> x
k = \x y -> x
ki = k i
true = k
false = ki
not = \p -> p false true
beq = \p q -> p (q true false) (q false true)
beq' = \p q -> p q (not q)
So I checked inferred types of theses.
*Main> :type beq
beq
:: (t1 -> t1 -> t2)
-> ((p1 -> p1 -> p1) -> (p2 -> p2 -> p2) -> t1) -> t2
*Main> :type beq'
beq'
:: (((p1 -> p2 -> p2) -> (p3 -> p4 -> p3) -> t1) -> t1 -> t2)
-> ((p1 -> p2 -> p2) -> (p3 -> p4 -> p3) -> t1) -> t2
And it was not equal.
Here are the questions.
I thought it has the same type signature because beq and beq' seemingly make the same result when it folded and substituted. Like there are many ways to implement one function. But it wasn't. Are there some secret rules and syntax in Haskell?
If I want to write beq with the function not, how can I make it works?

How to fix the encoding
Church encodings work very well in an untyped calculus.
When types are added, things get more complicated. With simple types, for instance, the encodings are lost. With polymorphism they can be recovered, if higher ranks are supported. Note that type inference can't work well with higher types, so some explicit type annotation is needed.
For example, your not should be written as:
{-# LANGUAGE RankNTypes #-}
type ChBool = forall a. a -> a -> a
not :: ChBool -> ChBool
not f x y = f y x
It is important that boolean values are modeled as polymorphic functions, since otherwise they can only be used on a single type, making many examples fail. For instance, consider
foo :: Bool -> (Int, String)
foo b = (b 3 2, b "aa" "bb")
Here b needs to be used twice, once on Ints and once on Strings. If Bool is not polymorphic this will fail.
Why beta-reduction changes the inferred type
Further, you seem to be convinced that you can beta-reduce Haskell expressions and the inferred type before and after the reduction must be the same. That's not true, in general, as you discovered in your experiments. To see why, here's a simple example:
id1 x = x
The inferred type here is id1 :: forall a. a -> a, obviously. Consider instead this variant:
id2 x = (\ _ -> x) e
Note that id2 beta-reduces to id1, whatever e might be. By choosing e carefully, though, we can restrict the type of x. E.g. let's choose e = x "hello"
id2 x = (\ _ -> x) (x "hello")
Now, the inferred type is id2 :: forall b. (String -> b) -> String -> b since x can only be a String-accepting function. It does not matter that e will not be evaluated, the type inference algorithm will make that well-typed anyway. This makes the inferred type of id2 differ from the one of id1.

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.

Type of anonymous functions in 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

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.

Type signatures that never make sense

Consider
(a->a) -> [a] -> Bool
Is there any meaningful definition for this signature? That is, a definition that not simply ignores the argument?
x -> [a] -> Bool
It seems there are many such signatures that can be ruled out immediately.
Carsten König suggested in a comment to use the free theorem. Let's try that.
Prime the cannon
We start by generating the free theorem corresponding to the type (a->a) -> [a] -> Bool. This is a property that every function with that type must satisfy, as established by the famous Wadler's paper Theorems for free!.
forall t1,t2 in TYPES, R in REL(t1,t2).
forall p :: t1 -> t1.
forall q :: t2 -> t2.
(forall (x, y) in R. (p x, q y) in R)
==> (forall (z, v) in lift{[]}(R). f_{t1} p z = f_{t2} q v)
lift{[]}(R)
= {([], [])}
u {(x : xs, y : ys) | ((x, y) in R) && ((xs, ys) in lift{[]}(R))}
An example
To better understand the theorem above, let's run over a concrete example. To use the theorem, we need to take any two types t1,t2, so we can pick t1=Bool and t2=Int.
Then we need to choose a function p :: Bool -> Bool (say p=not), and a function q :: Int -> Int (say q = \x -> 1-x).
Now, we need to define a relation R between Bools and Ints. Let's take the standard boolean
<->integer correspondence, i.e.:
R = {(False,0),(True,1)}
(the above is a one-one correspondence, but it does not have to be, in general).
Now we need to check that (forall (x, y) in R. (p x, q y) in R). We only have two cases to check for (x,y) in R:
Case (x,y) = (False,0): we verify that (not False, 1-0) = (True, 1) in R (ok!)
Case (x,y) = (True ,1): we verify that (not True , 1-1) = (False,0) in R (ok!)
So far so good. Now we need to "lift" the relation so to work on lists: e.g.
[True,False,False,False] is in relation with [1,0,0,0]
This extended relation is the one named lift{[]}(R) above.
Finally, the theorem states that, for any function f :: (a->a) -> [a] -> Bool we must have
f_Bool not [True,False,False,False] = f_Int (\x->1-x) [1,0,0,0]
where above f_Bool simply makes it explicit that f is used in the specialised case in which a=Bool.
The power of this lies in that we do not know what the code of f actually is. We are deducing what f must satisfy by only looking at its polymorphic type.
Since we get types from type inference, and we can turn types into theorems, we really get "theorems for free!".
Back to the original goal
We want to prove that f does not use its first argument, and that it does not care about its second list argument, either, except for its length.
For this, take R be the universally true relation. Then, lift{[]}(R) is a relation which relates two lists iff they have the same length.
The theorem then implies:
forall t1,t2 in TYPES.
forall p :: t1 -> t1.
forall q :: t2 -> t2.
forall z :: [t1].
forall v :: [t2].
length z = length v ==> f_{t1} p z = f_{t2} q v
Hence, f ignores the first argument and only cares about the length of the second one.
QED
You can't do anything interesting with x on it's own.
You can do stuff with [x]; for example, you can count how many nodes are in the list. So, for example,
foo :: (a -> a) -> [a] -> Bool
foo _ [] = True
foo _ (_:_) = False
bar :: x -> [a] -> Bool
bar _ [] = True
bar _ (_:_) = False
If you have an x and a function that turns an x into something else, you can do interesting stuff:
big :: (x -> Int) -> x -> Bool
big f n = if f n > 10 then True else False
If x belongs to some type class, then you can use all the methods of that class on it. (This is really a special-case of the previous one.)
double :: Num x => x -> x
double = (2*)
On the other hand, there are plenty of type signatures for which no valid functions exist:
magic :: x -> y
magic = -- erm... good luck with that!
I read somewhere that the type signatures involving only variables for which a real function exists are exactly the logical theorems that are true. (I don't know the name for this property, but it's quite interesting.)
f1 :: (x -> y) -> x -> y
-- Given that X implies Y, and given that X is true, then Y is true.
-- Well, duh.
f2 :: Either (x -> y) (x -> z) -> x -> Either y z
-- Given that X implies Y or X implies Z, and given X, then either Y or Z is true.
-- Again, duh.
f3 :: x -> y
-- Given that X is true, then any Y is true.
-- Erm, no. Just... no.

Resources