I am wondering for a while now what is f. Could someone provide an example to how I should be running this function?
(Note: I understand that the (.) is function composition and I know what function composition if)
-- compose a function n >= 0 times with itself
composeN :: Int -> (a -> a) -> (a -> a)
composeN 0 f = id
composeN n f = f . (composeN (n-1) f)
f is an arbitrary function, provided by the user. I could supply composeN with succ, to increment an integer, and have it be composed three times and applied to 2, thereby adding 3:
ghci> composeN 3 succ 2
5
Related
I think I understand how function application works when writing out the steps, but the type signature arithmetic doesn't add up in my head. Apologies for the long prelude (no pun intended).
To bring a specific example, this one is a slightly altered example from Stefan Höck's Idris2 tutorial:
plusTwo : Integer -> Integer
plusTwo = (+2)
twice : (Integer -> Integer) -> Integer -> Integer
twice f n = f (f n)
In the REPL(s):
> twice plusTwo 3
7
> (twice . twice) plusTwo 3
11
What I know
functions both in Haskell and Idris are curried and every function takes only one argument
function composition is implemented as
f . g = \x -> f (g x)
function application is left associative
arrows in type signatures are right associative
Writing out (twice . twice) plusTwo 3
The expression can be explicitly parenthesized as
((twice . twice) plusTwo) 3
which can be re-written as
------f-------- -n-
(twice (twice plusTwo)) 3
|
V
------f-------- (------f-------- -n-)
(twice plusTwo) ((twice plusTwo) 3 )
\------------------/
|||
plusTwo (plusTwo 3)
|||
7
\-----------------------------------/
|||
twice plusTwo 7
Seeming type signature mismatch
The function composition operator's type signature below shows that it takes one-argument functions,
(.) :: (b -> c) -> (a -> b) -> a -> c
f . g = \x -> f (g x)
but twice takes two arguments (i.e., (t -> t) -> t -> t), so this throws me off.
I guess the only way this works when the argument x of the returned lambda is itself a function. Could it be this simple?
twice . twice
((a -> a) -> a -> a) -> ((a -> a) -> a -> a) -> ?
(---b---- -> --c---) -> (---a---- -> --b---) -> (a -> c)
? = (a -> a) -> a -> a
or, to put it another way, twice . twice takes a function with the signature (a -> a) -> a (where a here is Integer).
If the above stuff is correct, then I can figure out function compositions where the participating functions have differing input arguments (e.g., twice . (+2)).
Yes, that's really all it is. It may make it easier to think about if you write the signature of twice as
twice :: (Integer -> Integer) -> (Integer -> Integer)
As you know, this is equivalent thanks to currying. Seen this way, twice is a function of one argument, and composing it with twice again seems perfectly sensible.
I am trying to define a function to find the absolute difference of two numbers, such that both
absoluteDifference 2 5
absoluteDifference 5 2
return 3.
Here is my best effort so far:
absoluteDifference :: Num a => a -> a -> a
absoluteDifference = abs . (-)
In my head, this applies abs to the result of subtracting two numbers. However, this gives me the error
* Could not deduce (Num (a -> a)) arising from a use of `abs'
(maybe you haven't applied a function to enough arguments?)
from the context: Num a
bound by the type signature for:
absoluteDifference :: Num a => a -> a -> a
at C:\Users\Adam\dev\daily-programmer\e311\e311.hs:3:1-42
* In the first argument of `(.)', namely `abs'
In the expression: abs . (-)
In an equation for `absoluteDifference':
absoluteDifference = abs . (-)
Which I don't understand. I could trivially implement the function as
absoluteDifference a b = abs $ a - b
but I want to know how to compose the functions.
The info for (.)
Prelude> :i (.)
(.) :: (b -> c) -> (a -> b) -> a -> c -- Defined in ‘GHC.Base’
shows that it accepts functions with types a -> b
but (-) has the type
Prelude> :i (-)
class Num a where
...
(-) :: a -> a -> a
...
-- Defined in ‘GHC.Num’
infixl 6 -
so, it is possible to define another composition operator that accepts functions having the above type, and then they can be composed.
of' :: (a -> a) -> (a -> a -> a) -> a -> a -> a
of' f g a b = f (g a b)
abdiff = abs `of'` (-)
abdiff 1 10
9
note: as user #david-young points out correctly, of' can be more general by specifying the type as below:
of' :: (a -> b) -> (c -> d -> a) -> c -> d -> b
of' f g x y = f (g x y)
Besides defining a custom operator, as suggested by Haleemur Ali's answer, one alternative is making the definition less point-free by having a single-argument function as the second argument of (.).
absoluteDifference a = abs . (-) a
Given how similar are the roles of the two arguments in your function, from a readability point of view it doesn't make much sense to write it in this way (though it might work better in other cases).
Another possibility is making it more point-free (by having a function-modifying function as the first argument of (-)):
absoluteDifference = (abs .) . (-)
While this is a nice parlour trick, this sort of code with (.) sections is rather cryptic, and it is generally a good idea to avoid it in "real" code.
Why not an owl operator?
(...) = (.) . (.)
absoluteDifference = abs ... (-)
Actually your answer is pretty close. All you need is to amend it as follows;
absDiff :: Num a => a -> a -> a
absDiff n = abs . (n-)
*Main> absDiff 3 9
6
*Main> absDiff 9 3
6
I struggle understanding function composition type results e.g
ghci> :t (id . const)
(id . const) :: a -> b -> a
ghci> :t ((:) . (+))
((:) . (+)) :: a -> [a -> a] -> [a -> a]
How do you guys generally derive function composition types?
That's simple, initially write down the types of both the functions:
> :t const
const :: a -> b -> a
> :t id
id :: a -> a
(id . const) gets translated to \x -> id (const x)
(const x) :: b -> a -- (Note that the type of `x` is `a` here)
id (const x) :: b -> a -- The output of id type will be the same as the input it takes
\x -> id (const x) :: a -> b -> a -- We aleady know the type of x
You can follow the same step for the next function.
Lets see that
> :t (.)
(.) :: (b -> c) -> (a -> b) -> a -> c
So in general:
Given two functions. Consider them as curried functions of one parameter, i.e. function of type
a -> b -> c -> ... -> z we'll consider as a function a -> ( b -> c -> ... -> z ) of one parameter that returns function with one parameter less.
Result type of second function should be same as parameter type of first. So consider parameter of first function as result parameter of second. Denote it as b.
Result type of whole composition should be equal a function from parameter type of second function (denote it as a) to result type of first function (denote it as c)
> :t (id . const)
> :t id
id :: a -> a
rename it to x -> x
> :t const
const :: a -> b -> a
Note that a here is not necessary the same that in previous type equation, some rename it to y -> z -> y
a = y
b = z -> y = x
c = x = z -> y
So result is a -> c = y -> ( z -> y) same as a -> b -> c
Overall semantics is equal to const
> :t ((:) . (+))
> :t (:)
(:) :: a -> [a] -> [a]
rename it to x -> [x] -> [x]
> :t (+)
(+) :: Num a => a -> a -> a
rename it to Num y => y -> y -> y
a = y
b = y -> y = x
c = [x] -> [x] = [y -> y] -> [y -> y]
Also we have restriction with type class Num y
So overall type well be Num y => a -> c = y -> [y -> y] -> [y -> y] same as Num a => a -> [a -> a] -> [a -> a]
Overall semantics is "make single parameter function that adds first parameter to numeric value and prepend that function to a given list of single parameter functions"
Exercises: Find the types of the function compositions below, by hand, not using GHCi. Do these exercises to build intuition for reasoning about function types. Remember that type a -> a, where a is a type variable, matches not only Int -> Int or [Bool] -> [Bool], but (a -> a) -> (a -> a) too. If you can't do the exercises, read below.
(*3) . (+2) (easy)
(*) . (+2)
(:) . (+2)
(:) . (*)
What is a function? It's something, that takes an input and returns an output. Not just random output, but output that depends on that input. For the same input the same function always returns the same output. A function transforms some stuff to another stuff. Input and output can be of different types. So imagine a function as a magical one-way tube: you put one thing in the hole labeled in and get something else from another hole named out, possibly of entirely different form. Like, you put a tomato in a tube and get a machine gun from the opposite end. But remember, functions are one-way, you can't put anything in the function's out hole.
a :: Int -> Int -- take a thing of type Int and return a thing of type Int
a n = n + 2
b :: Int -> Int
b n = n -- a function can even return the same value
c :: Int -> Bool -- an output can be of different type than input
c n = n `mod` 3 == 0
Haskell supports higher-order functions and is curried by default. This means that there are no multiple-argument functions in Haskell, every function accepts only 1 argument, but sometimes they can return functions. Haskell tubes always has one and only one hole in, but sometimes tubes pop tubes from the hole out! There are even tubes, in which you can put other tubes. Function types are right-associative, which means that a -> b -> c and a -> (b -> c) are the same thing.
:t (+) -- Num a => a -> a -> a
:t (:) -- a -> [a] -> [a]
So what's a function composition? It's when you compose functions into a new function, or when you fuse 2 tubes together, welding 1st's out to 2nd's in, so that whatever you put into the first tube's in hole, falls through and pops out of second tube's out hole.
A composed function then can be imagined as a long tube made out of two shorter tubes welded together. What would be the type of a composed function? Our new tube still has 2 holes in it, one labeled in, another labeled out. But remember, in of our new tube corresponded to in of a first part, and out of our new tube corresponded to out of the second part. So the type will be from whatever was input to 1st function to whatever was output of 2nd function.
:t (:[2,3]) . (+1) -- Num a => a -> [a]
-- why?
:t (+1) -- Num a => a -> a
:t (:[2,3]) -- Num a => a -> [a]
We joint 2 functions together, first's output to second's input, and get a new function that still has one input and one output. And that's exactly what function operator's type says:
:t (.) -- (b -> c) -> (a -> b) -> (a -> c)
Due to a historical accident, function composition goes from right to left, so (*3) . (+2) is a function that first adds 2 to a number, and then multiples by 3 the result. So how to deduce a type of a function composition? You joint the the input of 2nd function to an output of 1st function and throw away the types in between.
a -> b
b -> c becomes
a -> c
See also: [1], [2], [3], [4] for more ideas on how to use function composition and how to reason about function types.
Let's say I have two functions named f :: a -> b and it's inverse g :: b -> a such that f . g ≡ id.
Now isn't g . f ≡ id ? (And hence implying isomorphism)
I tried to write a similar example and came up with this:
myRead :: String -> Int
myRead = read
myShow :: Int -> String
myShow = show
In ghci:
λ> myRead . myShow $ 3
3
λ> myShow . myRead $ "33"
"33"
But it seems that the inverse function doesn't imply isomorphism. So can anybody point me on what I'm doing wrong here ?
Here's a really trivial example. If A is the set {1,2} and B the set {1} then the functions:
f :: A -> B
f = const 1
g :: B -> A
g 1 = 1
have the relation f . g = id but not the relation g . f = id. A counterexample is
g (f 2) = 1
It turns out that if you have two functions such that f . g = id and g . f = id then that says a whole lot about the domain and codomain of those functions. In particular, it establishes an isomorphism which suggests that those two domains are in some sense equivalent.
From a category theoretic perspective it means that they are indistinguishable via the morphisms of the category. Category theory emphasizes that the morphisms of the category are the only way to gain information about an object, so this indistinguishability is very important.
When you've got only one-sided inverses, you still are learning a lot about the two domains... but simply not that they're isomorphic.
One thing a one-sided inverse gives you is an idempotent. An idempotent is a function i from a domain to itself (an endomorphism) such that i . i = i. Given any two functions where f . g = id, g . f is an idempotent and the proof is quite obvious:
i . i = (g . f) . (g . f) = g . f . g . f = g . (f . g) . f = g . f = i
Another good thing to think about is that every function f :: A -> B produces the "inverse-image" function inv f :: B -> (A -> Bool).
inv :: Eq b => (a -> b) -> b -> a -> Bool
inv f b a = f a == b
In more mathematical terms, the inverse image function is a mapping from the codomain B to subsets of the domain A such that every element in each such subset of A maps to the same element of B. These subsets partition A (this is the definition of a function).
If we have another function g :: B -> A such that g b is in the subset inv f b (i.e. inv f b (g b) == True for all b) then we have
f . g == id
but this is far weaker and more technical than A and B just being isomorphic. It just means that g is sending elements of B to subsets of A which f will send right back.
For instance, it admits a whole interesting notion of the "fibration" of a space.
Using your own example, myRead . myShow ≡ id, but
(myShow . myRead) "0xFF" = "255"
so myShow . myRead ≢ id, and you could also see this by a counting argument:
The type Int has finitely many values while String has infinitely many, so while it is possible to go from Int to String and back, going from the infinite type String to the finite type Int must discard information, so you can't always get back to the original string and therefore it is impossible to construct an isomorphism between Int and String.
If g :: X -> Y is surjective, then there is not necessarily a reverse function f :: Y -> X. Yet, a surjective function g can reverse some function f.
Suppose for every y in Y there is a unique value x in X that f finds. It is feasible to specify a function g that for every such x in X finds y in Y such that g . f == id. This statement shows existence of unique x for all y, but this does not tell anything about existence of unique y for all x (i.e. the uniqueness is not guaranteed). (I am not even touching how g is built - you'd need axiom of choice).
Given the following function definition and assuming similar definitions for all positive integers give the type definition and code for a function called plus that will take as arguments two such functions representing integers and return a function that represents the sum of the two input integers. E.g. (plus one two) should evaluate to a function that takes two arguments f x and returns (f(f(f x))).
one f x = f x
two f x = f (f x)
three f x = f (f (f x)))
etc.
I am new to functional programming and I can't get my head around this. I firstly don't know how I can define the functions for all the positive integers without writing them out (which is obviously impossible). As in, if I have plus(sixty, forty), how can my function recognize that sixty is f applied 60 times to x?
I am meant to be writing this in Miranda, but I am more familiar with Haskell, so help for either is welcome.
Apply equational reasoning1, and abstraction. You have
one f x = f x -- :: (a -> b) -> a -> b
two f x = f (f x) -- = f (one f x) -- :: (a -> a) -> a -> a
three f x = f (f (f x)) -- = f (two f x) -- :: (a -> a) -> a -> a
-- ~~~~~~~~~~~
Thus, a successor function next is naturally defined, so that three = next two. Yes, it is as simple as writing next two instead of three in the equation above:
next :: ((b -> c) -> a -> b) -> (b -> c) -> a -> c
-- three f x = next two f x = f (two f x) -- `two` is a formal parameter
-- ~~~~~~~~~~~
next num f x = f (num f x) -- generic name `num`
zero :: t -> a -> a
zero f x = x
This captures the pattern of succession. f will be used as a successor function, and x as zero value. The rest follows. For instance,
plus :: (t -> b -> c) -> (t -> a -> b) -> t -> a -> c
plus two one f x = two f (one f x) -- formal parameters two, one
-- = f (f (one f x)) -- an example substitution
-- = f (f (f x) -- uses the global definitions
-- = three f x -- for one, two, three
i.e. one f x will be used as a zero value by two (instead of the "usual" x), thus representing three. A "number" n represents a succession of n +1 operations.
The above, again, actually defines the general plus operation because two and one are just two formal function parameters:
Prelude> plus three two succ 0 -- built-in `succ :: Enum a => a -> a`
5
Prelude> :t plus three two
plus three two :: (a -> a) -> a -> a
Prelude> plus three two (1:) [0]
[1,1,1,1,1,0]
The key thing to gasp here is that a function is an object that will produce a value, when called. In itself it's an opaque object. The "observer" arguments that we apply to it, supply the "meaning" for what it means to be zero, or to find a successor, and thus define what result is produced when we make an observation of a number's value.
1i.e. replace freely in any expression the LHS with the RHS of a definition, or the RHS with the LHS, as you see fit (up to the variables renaming of course, to not capture/shadow the existing free variables).
To convert a number to a numeral you can use something like:
type Numeral = forall a . (a -> a) -> (a -> a)
toChurch :: Int -> Numeral
toChurch 0 _ x = x
toChurch n f x = f $ toChurch (pred n) f x
fromChurch :: Numeral -> Int
fromChurch numeral = numeral succ 0
You don't need to recognize how many times the function is calling f. For example, to implement succ, which adds 1 to a Church numeral, you can do something like this:
succ n f x = f (n f x)
Then you first use n to apply f however many times it needs to, and then you do the final f yourself. You could also do it the other way round, and first apply f once yourself and then let n do the rest.
succ n f x = n f (f x)
You can use a similar technique to implement plus.