Boolean logic and types in haskell - haskell

I'm currently having Haskell for university. Given the following haskell code:
true::t -> t1 -> t
true = (\x y -> x)
false::t -> t1 -> t1
false = (\x y -> y)
-- Implication
(==>) = (\x y -> x y true)
The task is to determine the type of the function (==>).
GHCi says it is (==>) :: (t1 -> (t2 -> t3 -> t2) -> t) -> t1 -> t.
I can see that the evaluation order is the following (as the type stays the same):
(==>) = (\x y -> (x y) true)
So the function true ist argument to (x y).
Can anyone explain why the result type t is bound to the result of the first argument and in which way GHCi determines the type of (==>)?

First, to give a better overview,
type True t f = t -> f -> t
type False t f = t -> f -> f
Let's call the result of the implication r, then we have, in \x y -> x y true :: r, that
x y :: True t f -> r
so x :: y -> True t f -> r, and thus
(==>) :: (y -> True t f -> r) -> y -> r
which, expanding True again, is
(==>) :: (y -> (t->f->t) -> r) -> y -> r

Related

Understanding types in Haskell (lambda epxressions and higher order functions)

I'm currently doing a course in Haskell, and I have a lot of difficulty understanding the types of functions, particularly when there's function application or lambda expressions. Say for instance the following:
f = (\x -> \y -> \z -> [x (y z), y z])
or
g = \x -> \y -> \z -> x.y.z
I can sort of make some assumptions about the fact that x and y are functions, but I don't have a concrete method for figuring out the types of these functions.
Similarly for the following:
h = foldr (&&)
I try to guess and then check via :t in the interpreter, but I'm usually off by quite a bit.
Is there any particular method I can use to find the types of such functions?
You start by assigning type variables to the inputs and the result
f = (\x -> \y -> \z -> [x (y z), y z])
and conclude
f :: a -> b -> c -> d -- (A0)
-- or even (f is not needed)
\x -> \y -> \z -> [x (y z), y z] :: a -> b -> c -> d
that is
x :: a -- (1)
y :: b -- (2)
z :: c -- (3)
[x (y z), y z] :: d -- (4)
You can continue with (4) and conclude
that the type d is a list of d1s, i.e. d ~ [d1] (5)
f :: a -> b -> c -> [d1] -- (A1)
and that the values of the list are of type d1, i.e.
x (y z) :: d1 -- (6)
y z :: d1 -- (7)
From (6) you learn that
x :: e -> d1 -- (8)
y z :: e -- (9)
(1) and (8) unify, i.e. a ~ (e -> d1) and
f :: (e -> d1) -> b -> c -> [d1] -- (A2)
You play this game until you get bored and use GHCi to arrive at
f :: (d1 -> d1) -> (f -> d1) -> f -> [d1] -- (A3)
-- and renaming
f :: (a -> a) -> (b -> a) -> b -> [a] -- (A4)
If you want to learn more and read a paper you can start with Principal type-schemes for functional programs.
Prelude> :t h
h :: Foldable t => Bool -> t Bool -> Bool
Prelude> :t foldr
foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
Prelude> :t (&&)
(&&) :: Bool -> Bool -> Bool
Prelude>
By "plugging in" (&&) you have removed (a -> b -> b)
so you need to provide the rest to the function
b -> t a -> b
That is restricted by (&&) to be a bool as second param to it, and the second parameter is the t a which is also restricted to being a bool. since a and b needs to be the same type as in the (a->b->b) function.

Manual inferring type of (\x y z -> (x y) z)

I would like to understand how to get manual to the correct type of this Haskell expression.
(\x y z -> (x y) z)
In general I understand roughly how to manually determine the correct type, but with lambda expressions I am totally confused.
There's a fast way to get the type and a slow way. The slow way is below and does not remove any unnecessary parentheses.
The fast way (for this function)
Let us remember the properties of Haskell functions, namely for
f :: a -> b -> c
Both f x y and (f x) y are the same, as a -> b -> c is a -> (b -> c).
Thus \x y z -> (x y) z is the same as \x y z -> x y z. Therefore, if y's and z's type where a and b resp., then x's type is a -> b -> c:
\x y z -> x y z :: (a -> b -> c) -> a -> b -> c
If we named that function, then we would write:
f :: (a -> b -> c) -> a -> b -> c
f x y z = x y z
or even simpler:
f :: (a -> b -> c) -> a -> b -> c
f = id
as it is the identify function restrained to a function type. You can add parentheses around a -> b -> c in the type to see that, as a -> b -> c is a -> (b -> c):
f :: (a -> b -> c) -> (a -> b -> c)
f = id
The "slow" way
Let's start first by giving the lambda a name. This will enable us to use type signatures and continue from there:
f = \x y z -> (x y) z
Next, we use the regular function syntax instead of the lambda syntax:
f :: A -> B -> C -> D
f x y z = (x y) z
Now, we need to figure out A, B, C and D. Due to x being applied to y, we notice that A must be some function type, e.g. B -> ...?. Next we notice that x y must also be a function. Therefore, A needs to be B -> G, and G needs to be a function again. Since G is able to use z and therefore a value of type C, we know that G is G = C -> D:
f :: (B -> (C -> D)) -> B -> C -> D
We now have x's type, it's B -> (C -> D). Since neither y nor z are restrained, we can now change all type placeholders into type varialbles and end up with:
f :: (b -> (c -> d)) -> b -> c -> d
f x y z = (x y) z
For a last step, let's rename those variables:
f :: (a -> (b -> c)) -> a -> b -> c
f x y z = (x y) z
And that's \x y z -> (x y) z's type: (a -> (b -> c)) -> a -> b -> c.

haskell function type simplifyed f :: ((b -> a ) -> a -> c ) -> (b -> a ) -> b -> c [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
Just looking for an explanation of the type of this function, please
f x y z = x y (y z)
Prelude says is
f :: ((b -> a) -> a -> c) -> (b -> a) -> b -> c
But I'm not able getting that result with any known method ¬¬
Best regards.
Ugh, those “manually typecheck this expression” exercises are so silly. I don't know why lecturers keep putting them in assignments.
In practice, what's actually much more relevant is to go the other way around: given a type, find an implementation. So let me answer the question from that angle: you already know
f :: ((b -> a) -> a -> c) -> (b -> a) -> b -> c
-- └──────────────────┘ └──────┘ └─┘
...so you have three arguments to accept, reasonable enough to call them x, y and z
f x y z = _
You're in the end looking for a c, and the only c you have available is in the final result of x
x :: (b -> a) -> a -> c
-- └──────┘ └─┘
...which requires two arguments
f x y z = x _ _
...of types b -> a and a. Let's check what we have available
y :: b -> a
z :: b
Great, we can directly use y as the first argument
f x y z = x y _
For the second argument we need an a. Well, z is a b, that doesn't work, but y yields an a when given a b, so we can pass y z and thus end up with
f x y z = x y (y z)
or as we prefer to write it in Haskell, f x y = x y . y.
Now for the other way around: let's start with the η-reduced form
f x y = x y . y
This is a pipeline, so let's start giving the passing-through argument a name p
x y . y :: p -> _
That argument is passed first to y, so we have
y :: p -> _
from which it follows, since y is also the first argument to x
x :: (p -> _) -> _
Furthermore, x then accepts (in the pipeline) whatever comes out of y
y :: p -> r
x :: (p -> r) -> r -> _
Let's call the final result q
y :: p -> r
x :: (p -> r) -> r -> q
And write up the whole function as given:
(\x y -> x y . y) :: ((p -> r) -> r -> q) -> (p -> r) -> p -> q
-- └─────────x────────┘ └──y───┘
Which is, after renaming the type variables, the same as what you started with.
From f x y z = x y (y z), you can reason as follows:
We don't apply z to anything, so it could have some arbitrary type; call it u1 (for unknown number one).
y is applied to z, so its argument type is u1, but the return type is another unknown type u2. Thus y :: u1 -> u2.
y z thus has type u2.
x is applied to y and y z, and so must have a type like (u1 -> u2) -> u2 -> u3; there's no reason to assume that either argument has the same type, or that either type is the same as the return type.
The return value of f is the same as the return value of x, i.e. u3.
Putting it altogether, we have
f :: ((u1 -> u2) -> u2 -> u3) -> (u1 -> u2) -> u1 -> u3
------------------------ ---------- -- --
type of x type of y type of z end result of f
Because the names of the individual type variables aren't important aside from keeping distinct types separate, we can rename them using
u1 ~ b
u2 ~ a
u3 ~ c
to get the type you looked up
f :: ((b -> a) -> a -> c) -> (b -> a) -> b -> c

Trying to implement elem with a foldl any

I am new in haskell, i am trying right now to implement "elem" with a "foldl any" in Haskell, but it won't work.
My any :
any' p = foldl' (\y x -> p x || y) False
and this is my elem :
elem' y = foldl' (\z x -> x==y || z) False
my first try was this :
elemfa p y = not (any' (\x -> not (p x)) y)
but i am getting an error everytime
Your elemfa :: Foldable f => (a -> Bool) -> f a -> Bool makes use of any'''', but that function does not exists. If you rewrite this to:
elemfa :: Foldable f => (a -> Bool) -> f a -> Bool
elemfa p y = not (any' (\x -> not (p x)) y)
You can make it more clean with:
elemfa :: Foldable f => (a -> Bool) -> f a -> Bool
elemfa p = not . any' (not . p)
It will at least produce output. This function will check if all elements satisfy the given predicate.
That being said, it is not ideal to use a foldl here for any, elem and elemfa, since that means it will keep iterating over the list, even if it found an element that satisfies the predicate. If you thus work on an infinite list, it will not return True, even if it found an element:
Prelude Data.List> elem' 1 (1 : repeat 2)
… keeps looking …
Here foldr :: Foldable f => (a -> b -> b) -> b -> f a -> b can be used to stop searching once the element has been found, for example:
any' :: Foldable f => (a -> Bool) -> f a -> Bool
any' p = foldr (\x -> (p x ||)) False
elem' :: (Foldable f, Eq a) => a -> f a -> Bool
elem' x = any' (x==)
all' :: Foldable f => (a -> Bool) -> f a -> Bool
all' p = not . any (not . p)

Confused with nested lambda types in haskell

Just trying to see the types of some lambda expressions like this one:
:t \x -> (\y -> x y)
\x -> (\y -> x y) :: (t1 -> t2) -> t1 -> t2
shouldn't the type here be t1->(t2->t1->t2) ?
Similarly
:t \x -> (\y -> (\k -> y (x k)))
\x -> (\y -> (\k -> y (x k)))
:: (t1 -> t2) -> (t2 -> t3) -> t1 -> t3
Shouldn't the type be t1->(t2->(t3->t2))?
:t \x -> (\y -> x y)
\x -> (\y -> x y) :: (t1 -> t2) -> t1 -> t2
shouldn't the type here be t1->(t2->t1->t2) ?
No, t1->(t2->t1->t2) is the same as t1->t2->t1->t2 which is the type of a three-arguments function (of type t1, t2, and t1) returning t2. However, there are only two lambdas, for the two arguments x and y.
The right type is instead
typeOfX -> (typeofY -> typeOfResult)
\x -> (\y -> x y)
(By the way, none of the parentheses above are needed.)
What is typeOfResult? Is is the type of x y, so it is the return type for x which must be a function.
In order for the code to type check, we must then have that typeOfX is a function type, say a -> b. In such case we can see that typeOfResult = b. Further, in x y we pass y to x, and this can type check only if typeOfY = a.
So,
typeOfX -> typeofY -> typeOfResult
=
(a -> b) -> a -> b
The compiler used names t1 and t2, but this is the same type.
Parentheses here matter, since we must remember that x is a function a -> b.
Without parentheses we would get a three-argument function, as explained above.
You can try to apply the same reasoning to the second example. Start from
typeOfX -> typeofY -> typeOfK -> TypeOfResult, and slowly discover what these types actually are.
The type of x in \x -> \y -> x y is t1 -> t2, and it's the first argument.
As the outermost lambda, it gets applied first, followed by y
You could've written it as \x y -> x y which is just function application in the natural order.

Resources