Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The type and definition of a function that is formed from two given functions

Tags:

haskell

I was asked to write the most simple definition of the result of s k k, where

s = \ f g x -> f x (g x)
s :: (t1 -> t2 -> t3) -> (t1 -> t2) -> t1 -> t3
k = \ x y -> x
k :: p1 -> p2 -> p1

Writing :t s k k in the terminal gives: t -> t.

I think s takes two functions - f and g. where f takes t1 and t2 as inputs and returns t3. function g takes t1 as input and returns t2, and x is t1. Why is t3 the return type?

I think I understand function k, where you take x and y as inputs and the type of x is output. Is there a common approach when it comes to understanding how these two functions will work together forming s k k.

I also tried going step by step typing :t s k, which gives (t3 -> t2) -> t3 -> t3, however, that didn't help me too much :) Can someone explain this to someone new to Haskell?

like image 692
Anders Stene Avatar asked Sep 10 '21 18:09

Anders Stene


People also ask

What are the two types of functions?

Ans. 2 The different types of functions are as follows: many to one function, one to one function, onto function, one and onto function, constant function, the identity function, quadratic function, polynomial function, modulus function, rational function, signum function, greatest integer function and so on.

WHAT IS function and its type define any two with an example?

A function is a relation between a set of inputs and a set of permissible outputs with the property that each input is related to exactly one output. Let A & B be any two non-empty sets, mapping from A to B will be a function only when every element in set A has one end only one image in set B.

What are the 4 types of functions?

The types of functions can be broadly classified into four types. Based on Element: One to one Function, many to one function, onto function, one to one and onto function, into function.

What is a a function?

A function is a process or a relation that associates each element x of a set X, the domain of the function, to a single element y of another set Y (possibly the same set), the codomain of the function.

What are the types of functions in math?

Types of Functions In terms of relations, we can define the types of functions as: One to one function or Injective function: A function f: P → Q is said to be one to one if for each element of P there is a distinct element of Q. Many to one function: A function which maps two or more elements of P to the same element of set Q.

What is a G-function?

These include known derivatives, known integrals, and the ability to use software to manipulate the functions. Although this is indeed labeled as a “G-Function”, it isn’t a “known” one. All that’s needed is to rewrite the expression in the brackets so that the function becomes a “named function.”

What does it mean to specify a function?

Specifying a function. Given a function , by definition, to each element of the domain of the function , there is a unique element associated to it, the value () of at . There are several ways to specify or describe how is related to (), both explicitly and implicitly. Sometimes, a ...


Video Answer


2 Answers

If fun :: a1 -> b and arg :: a2, then the application fun arg :: b and a1 ~ a2 (a1 is equal to a2).

s k k is the same as (s k) k because function application associates to the left. So we have an application s k:

s   :: (t1 -> t2 -> t3) -> (t1 -> t2) -> t1 -> t3
k   :: (p1 -> p2 -> p1)

s k ::                     (t1 -> t2) -> t1 -> t3

p1 ~ t1
p2 ~ t2
p1 ~ t3

Note that p1 ~ t1 and p1 ~ t3, therefore t1 ~ t3:

s k ::                     (t1 -> t2) -> t1 -> t1

In the application (s k) k, a similar thing happens; I’ll rename the type variables with a prime ' to indicate that this is a different instantiation of k’s type:

(s k)   :: (t1  -> t2        ) -> t1 -> t1
      k :: (p1' -> p2' -> p1')

(s k) k ::                        t1 -> t1

t1 ~ p1'
t2 ~ p2' -> p1'

Notice that when t1 -> t2 is unified with p1' -> p2' -> p1', which is equal to p1' -> (p2' -> p1') because function types are right-associative, t2 is equated with the function type p2' -> p1'.

As a result, the type of the whole expression is t1 -> t1, or forall t1. t1 -> t1 with ExplicitForAll. Even without knowing the term here, there is only one function (which is total) of the type forall a. a -> a, and that is id. Indeed s k k is just a roundabout way of implementing the identity function, because for any X we give it, it returns X:

s k k X
(\ f g x -> f x (g x)) k k X
(\ g x -> k x (g x)) k X
(\ x -> k x (k x)) X
k X (k X)
(\ x y -> x) X (k X)
(\ y -> X) (k X)
X

The first k selects X, and the second application of k is ignored. That’s why neither of the type variables from the second use of k (p1' and p2') appear in the resulting type.

like image 67
Jon Purdy Avatar answered Oct 17 '22 23:10

Jon Purdy


Well we know from their definitions that

s k k x = k x (k x) = x 

-- s = \f g x -> f x (g x)
-- s    k k x =  k x (k x)

-- k = \ x  y    -> x
-- k     x  y    =  x
-- k     x (k x) =  x

so that

s k k = \ x -> x

and thus its type is

a -> a

GHCi concurs (as you've already noted):

> :t s k k
s k k :: t3 -> t3

As to the types in s you ask about,

s :: (t1 -> t2 -> t3) -> (t1 -> t2) -> t1 -> t3
s = \ f g x -> f x (g x)
s     f g x =  f x (g x)
--
--         x  :: t1
--       g    :: t1 -> t2
--       g x  ::       t2
--    x       :: t1
--  f         :: t1 -> t2 -> t3
--  f x (g x) ::             t3

just follow from the most basic rule of type inference in application,

        x  ::  A                          x :: a
      f    ::  A -> B                   f   :: b -> c
    -------------------                --------------
      f x  ::       B                   f x ::      c  , a ~ b

This is analogous to Modus Ponens in logic, "if we have A, and A implies B, then B holds as well".


If you wanted to get this from the types of s and k a.o.t. their definitions, a similar kind of diagram works for that as well:

s     :: (a -> b -> c) -> (a ->     b    ) -> a -> c
  k   ::  x -> y -> x
-------  a~x, b~y, c~x  => c~x~a  -------------------
s k   ::                  (a  ->    b    ) -> a -> a
    k ::                   x2 -> y2 -> x2
----------------------  a~x2, b~(y2 -> x2)  ---------
s k k ::                                      a -> a

(you can see the type you asked about, s k :: (a->b)->a->a, there). Here you can see the type unifications done "step by step" but the two unifications could well have been done together,

s     :: (a -> b -> c) -> (a ->     b    ) -> a -> c
  k   ::  x -> y -> x
    k ::                   x2 -> y2 -> x2
-------  a~x, b~y, c~x  => c~x~a  -------------------
----------------------  a~x2, b~(y2 -> x2)  ---------
s k k ::                                      a -> a

The end result is of course the same. Whether we read the above diagram at once or in stages, it's the same diagram. Currying is nice, and it works. And since it works, when you've already applied a thing to two other things you needn't concern yourself with the partial application in stages. Except maybe as a mental exercise.

There's nothing much to say about all these interim types really. You just write them one under the other, being careful to rename the variables consistently at different invocations to avoid capture, noting the resulting equivalences and using them to simplify the resulting types.

Last thing to notice is that s k s and s k (s k) etc. could also be used for the same purpose. Almost, just like ($) is almost the same as id.

like image 20
Will Ness Avatar answered Oct 17 '22 23:10

Will Ness