I have to derive the type of this function:
func x = map -1 x
And I've already found a way, using a tip to change it to a lambda expression:
func = \x -> (map) - (1 x)
If I express it like that, its fine and I get the same type as the original, but I'm not sure why its grouped like this. Could someone explain it?
For example, why isn't it like this:
func = \x -> (map - 1) x
or something similar.
I know it's a useless function etc. but I can't change the function, I just have to derive its type.
If you write this function in a file, eg:
test.hs has func x = map -1 x
and use :t func in the interpreter, it will reply:
func :: (Num (t -> (a -> b) -> [a] -> [b]),
Num ((a -> b) -> [a] -> [b])) =>
t -> (a -> b) -> [a] -> [b]
I now believe you meant to ask why
func x = map -1 x
has the type (Num (t -> (a -> b) -> [a] -> [b]), Num ((a -> b) -> [a] -> [b])) => t -> (a -> b) -> [a] -> [b], and how you can bracket the expression to make it have that type.
First, you have to recognise that the space is an operator in haskell, and has the highest precedence of all.
Let's use # instead of space, with highest precedence we can:
infixl 9 #
f # x = f x
We can replace and space without an operator with #:
func x = map - 1 # x
because the space between 1 and x was the only one without an operator (- is between map and 1).
Since # has higher precedence than -, we get
func x = map - (1 # x)
or equivalently
func x = map - (1 x)
Another example
func2 x = map (-1) x
> :t func2
func2 :: Num (a -> b) => [a] -> [b]
This translates as
func2' x = map # (-1) # x
but why isn't there a # between the - and the 1? In this case, - in front of a numeric literal like 1 means negate:
> (-1)
-1
> (negate 1)
-1
> (subtract 1)
<interactive>:73:1:
No instance for (Show (a0 -> a0))
arising from a use of `print'
Possible fix: add an instance declaration for (Show (a0 -> a0))
In a stmt of an interactive GHCi command: print it
So this function is trying to map the negative of 1 over a list. For that to work, it would need negative 1 to be a function, which is why it needs a numeric instance for functions (the Num (a->b) => at the start of the type).
but i'm not sure why its grouped like this. Could someone explain it? In example, why its not like that:
func = \x -> (map - 1) x
Precedence. The language definition specifies that the precedence of (prefix) function application is higher than that of any infix operator, so
map -1 x
is parsed as the application of the infix operator (-) to the two operands map and 1 x, like 3 + 4 * 5 is parsed 3 + (4 * 5) due to the higher precedence of (*) compared to that of (+).
Although the interpreter has assigned a type to the expression, it's not a sensible one. Let's see what the function should be
func x = map -1 x
looks like we want to bracket that like this
func x = map (-1) x
in the hope that it subtracts one from each element of a list, but unfortunately, the - is considered to be negation when it's in front of a numeric literal, so we need to bracket it to change it into the subtraction function:
func x = map ((-) 1) x
Now this function subtracts each number in the list from 1:
func [1,2,3]
=[(-) 1 1, (-) 1 2, (-) 1 3]
=[ 1-1, 1-2, 1-3]
=[ 0, -1, -2]
The type is
func :: Num a => [a] -> [a]
If you wanted to subtract one from each element of the list, rather than subtracting each element of the list from 1, you could use func x = map (subtract 1) x. As hammar points out, the subtract function exists exactly for the purpose of allowing this.
Your alternative
func = \x -> (map - 1) x
This can't work because (-) has type Num a => a -> a -> a, whereas map has type (a -> b) -> [a] -> [b]. You can't subtract one from a function, because a function isn't a numeric value.
Related
I'd like to compose the addition operator (+) to make a function of this type:
Num a => a -> a -> a -> a
Like, the equivalent of this:
(\a b c -> a + b + c)
but without having to resort to lambdas.
I tried already
((+) . (+))
which I would have expected to work but surprisingly didn't.
http://pointfree.io gives the point-free version of \a b c -> a + b + c as ((+) .) . (+).
Informally, composition only works "intuitively" for first-order functions, which neither take functions as arguments nor return functions as values. (+) is a higher-order function; it takes a value of type Num a => a, and returns a function of type Num a => a -> a. When you try to compose higher-order functions in a naive fashion, the result is not what you expect:
:t (+) . (+)
(+) . (+) :: (Num a, Num (a -> a)) => a -> (a -> a) -> a -> a
Consider the definitions of the two functions:
(+) :: Num z => z -> z -> z
(.) :: (b -> c) -> (a -> b) -> (a -> c)
f . g = \x -> f (g x)
Then
(+) . (+) == (.) (+) (+)
== \x -> (+) ((+) x)
Because of currying, you wind up passing a function, not a number, as the first argument of the first (+).
So how do we get from h a b c = a + b + c to h = ((+) .) . (+)? Start by rewriting the infix expression as a prefix expression, using the fact that (+) is left-associative.
\a b c -> a + b + c
== \a b c -> ((+) a b ) + c
== \a b c -> (+) ((+) a b) c
Next, we alternately apply eta conversion to eliminate an argument and composition to move an argument into position to be eliminated. I've tried to be very explicit about identifying the functions use for the application of composition.
== \a b -> (+) ((+) a b) -- eta conversion to eliminate c
== \a b -> (+) (((+) a) b) -- parentheses justified by currying
-- f g -- f = (+), g = ((+) a)
-- \a b -> f ( g b)
-- \a b -> (f . g) b -- definition of (.)
== \a b -> ((+) . ((+) a)) b
== \a -> (+) . ((+) a) -- eta conversion to eliminate b
== \a -> (.) (+) ((+) a) -- prefix notation
== \a -> ((.) (+)) ((+) a) -- parentheses justified by currying
== \a -> ((+) . )((+) a) -- back to a section of (.)
-- f g -- f = ((+) .), g = (+)
-- \a -> f (g a)
-- \a -> ( f . g) a -- definition of (.)
== \a -> (((+) .) . (+)) a
== ((+) .) . (+) -- eta conversion to eliminate a
You need this strange operator (.).(.), which is sometimes defines as .: (think of 3 dots ...)
In ghci
Prelude> let (.:) = (.).(.)
Prelude> let f = (+) .: (+)
Prelude> f 1 2 3
> 6
Note this operator can also be defined as <$$> = fmap . fmap.
Although this introduces some noise, you could use uncurry :: (a -> b -> c) -> (a,b) -> c and curry :: ((a,b) -> c) -> a -> b -> c to temporary store the arguments of the second plus in one tuple:
curry $ (+) . uncurry (+) :: Num a => a -> a -> a -> a
or perhaps more semantically readable:
curry ((+) . uncurry (+)) :: Num a => a -> a -> a -> a
uncurry thus takes a function (here (+)) and transforms it into a function: uncurry (+) :: Num a => (a,a) -> a. So as a result you have transformed the (+) into a function that takes a tuple.
Now we can use (.) to make a composition with the first (+):
(+) . uncurry (+) :: Num a => (a,a) -> (a -> a)
So now we have a function that takes one argument (the tuple (a,a)) and produces a function that takes an a (the second operand of the first (+)) and calculates the sum. The problem is of course that we want to get rid of the tuple. We can do so by passing the function into a curry. That transforms the tuple-function ((a,a) -> (a -> a)) into a function taking the arguments separately (a -> (a -> (a -> a))).
Note the signature of the function composition operator:
(.) :: (b -> c) -> (a -> b) -> a -> c
^ ^ ^
Functions
It takes 2 functions, each which take 1 argument, and returns a function that takes an argument of the same type as the second function, and returns the same type as the first.
Your attempt to compose two +s didn't work since + takes 2 arguments, so without some hackish/creative workaround, this isn't possible.
At this point, I'd say forcing composition when it doesn't fit the problem is just going to make your life more difficult.
If you want to sum up multiple numbers, you could write a function like:
sum :: [Int] -> Int
sum nums = foldl (+) 0 nums
Or, since nums appears at the back of the definition, it can be dropped altogether, yielding a "point-free" form:
sum :: [Int] -> Int
sum = foldl (+) 0
It reduces/folds + over a list of numbers. If you haven't used folds yet, look into them now. They are one of the main ways to achieve looping in Haskell. It's essentially "implicit recursion" when you're dealing with lists, or anything else iterable.
With the above function defined, you can use it like:
sum [1, 2 3, 4, 5]
What does the following expression means in haskell?
($ 3)
ghci shows the following type
($ 3) :: Num a => (a -> b) -> b.
($ 3) is a section, and is equivalent to \f -> f 3, which takes a function argument and applies it to 3.
If we considered 3 to be an integer, we would have that the type of f is Int -> b (for any b), so the type of ($ 3) would be (Int -> b) -> b.
Things in Haskell are a bit more complex, since 3 can be of any numeric type, so we don't really need f :: Int -> b, it's enough if f :: a -> b where a is a numeric type.
Hence we get ($ 3) :: Num a => (a -> b) -> b.
(# x) for any operator # is equivalent to \a -> a # x; so ($ 3) is equivalent to \f -> f $ 3, i.e. a function that applies any function you pass it to 3. This syntax is called "sections".
> let f = ($ 3)
> f show
"3"
> f square
9
Another way to look at it is
($) :: (a -> b) -> a -> b
3 :: Num a => a
and when you "insert 3" in the ($) it will become
($ 3) :: Num a => (a -> b) -> b.
due to that you no longer need to supply the a, but the function you need to supply is now restricted to num, since the 3 can be any numeric type.
This is at least how I look at functions in Haskell, like substitution in algebra.
I start to learn Haskell. While studying a tutorial I have found the following example that enables the usage of functions in arithmetic expressions:
module FunNat where
instance Num a => Num (t -> a) where
(+) = fun2 (+)
(*) = fun2 (*)
(-) = fun2 (-)
abs = fun1 abs
signum = fun1 signum
fromInteger = const . fromInteger
fun1 :: (a -> b) -> ((t -> a) -> (t -> b))
fun1 = (.)
fun2 :: (a -> b -> c) -> ((t -> a) -> (t -> b) -> (t -> c))
fun2 op a b = \t -> a t `op` b t
The example works. But I can not understand how the (+) function is transformed into the function of two arguments. As I can understand each (+) is substituted with fun2 (+). And fun2 is equivalent to the function of one argument \t -> a t 'op' b t, but we should have a function of two arguments (something like (\t1 t2 -> (\x -> x ) t1 + (\x -> x) t2) ). I think that here some basic concepts of Haskell typing should be applied but I do not know what they are.
EDIT 1
I understand that fun2 is a function of three arguments. I can't understand internal expression transformation. I'm reasoning in the following way: (+) 3 4 = (+) (\x->3) (\x->4) = fun2 (+) (\x->3) (\x->4) = \t -> (\x->3) t + (\x->4) t
What is this t? Or where am I wrong in my reasoning? May be it is necessary to think another way?
EDIT 2
I think that I have reached some understanding of the issue (thanks you all!). So:
When we write (+) 3 4 - in this case a simple operation from Num is used, no special features from FunNat. To use (+) from FunNat it is necessary to write fun2 (+) 3 4 or fun2 (+) (\x -> 3) (\x -> 4). But these expressions expect any third parameter to be evaluated;
To demonstrate specific features from FunNat we may use the following example ((*)-(+)) (taken from tutorial) or in other form - (-) (*) (+). Both expressions take two arguments. In this case we have: ((*)-(+)) = fun2 (-) (*) (+) = \t -> (*) t - (+) t = \t -> (\t1 t2 -> t1 * t2) t - (\t1 t2 -> t1 + t2) t = (\t t2 -> t * t2) - (\t t2 -> t + t2) = \t t2 -> (t * t2) - (t + t2). The final expression expects just Num. I hope that all these are correct
As it was explained in tutorial, but I can't understand what for, the possibility to use (*) and (+) as parameters for fun2 that expects (t->a) is based on the following (taken from tutorial): t1 -> t2 -> a = t1->a' where a' = t2 -> a. Here curring is used.
So all necessary facts were on the surface but I do not take into consideration the non-trivial mechanism of type inference.
The type of (+) is Num a => a -> a -> a. Since you're creating an instance of Num for the type Num a => t -> a, consider the explicit signature
(+) :: Num a => (t -> a) -> (t -> a) -> (t -> a) (1)
or equivalently (by currying)
(+) :: Num a => (t -> a) -> (t -> a) -> t -> a (2)
What this says is: "If you give me 2 strategies for producing a Num a => a from a t, I can create a new strategy for producing a Num a => a from a t by using the Num.(+) instance of the a's"
I think the part that has you confused is that this specific (+) can be viewed as a function of 2 arguments which returns a function (1), or a function of 3 arguments which returns a value (2). Since functions in Haskell are curried, these are really the same thing.
In type signatures parentheses associate to the right, so:
f :: a -> (b -> c -> d)
is the same as:
f :: a -> b -> c -> d
So the parens indicated below are redundant:
fun2 :: (a -> b -> c) -> ((t -> a) -> (t -> b) -> (t -> c))
^ ^
and removing them leaves:
fun2 :: (a -> b -> c) -> (t -> a) -> (t -> b) -> (t -> c)
arg1 arg2 arg3
I'm a relatively experienced Haskell programmer with a few hours of experience, so the answer might be obvious.
After watching A taste of Haskell, I got lost when Simon explained how the append (++) function really works with its arguments.
So, here's the part where he talks about this.
First, he says that (++) :: [a] -> [a] -> [a] can be understood as a function which gets two lists as arguments, and returns a list after the last arrow). However, he adds that actually, something like this happens: (++) :: [a] -> ([a] -> [a]), the function takes only one argument and returns a function.
I'm not sure to understand how the returned function closure gets the first list as it expects one argument as well.
On the next slide of the presentation, we have the following implementation:
(++) :: [a] -> [a] -> [a]
[] ++ ys = ys
(x:xs) ++ ys = x : (xs ++ ys)
If I think that (++) receives two arguments and return a list, this piece of code along with the recursion is clear enough.
If we consider that (++) receives only one argument and returns a list, where does ys come from? Where is the returned function ?
The trick to understanding this is that all haskell functions only take 1 argument at most, it's just that the implicit parentheses in the type signature and syntax sugar make it appear as if there are more arguments. To use ++ as an example, the following transformations are all equivalent
xs ++ ys = ...
(++) xs ys = ...
(++) xs = \ys -> ...
(++) = \xs -> (\ys -> ...)
(++) = \xs ys -> ...
Another quick example:
doubleList :: [Int] -> [Int]
doubleList = map (*2)
Here we have a function of one argument doubleList without any explicit arguments. It would have been equivalent to write
doubleList x = map (*2) x
Or any of the following
doubleList = \x -> map (*2) x
doubleList = \x -> map (\y -> y * 2) x
doubleList x = map (\y -> y * 2) x
doubleList = map (\y -> y * 2)
The first definition of doubleList is written in what is commonly called point-free notation, so called because in the mathematical theory backing it the arguments are referred to as "points", so point-free is "without arguments".
A more complex example:
func = \x y z -> x * y + z
func = \x -> \y z -> x * y + z
func x = \y z -> x * y + z
func x = \y -> \z -> x * y + z
func x y = \z -> x * y + z
func x y z = x * y + z
Now if we wanted to completely remove all references to the arguments we can make use of the . operator which performs function composition:
func x y z = (+) (x * y) z -- Make the + prefix
func x y = (+) (x * y) -- Now z becomes implicit
func x y = (+) ((*) x y) -- Make the * prefix
func x y = ((+) . ((*) x)) y -- Rewrite using composition
func x = (+) . ((*) x) -- Now y becomes implicit
func x = (.) (+) ((*) x) -- Make the . prefix
func x = ((.) (+)) ((*) x) -- Make implicit parens explicit
func x = (((.) (+)) . (*)) x -- Rewrite using composition
func = ((.) (+)) . (*) -- Now x becomes implicit
func = (.) ((.) (+)) (*) -- Make the . prefix
So as you can see there are lots of different ways to write a particular function with a varying number of explicit "arguments", some of which are very readable (i.e. func x y z = x * y + z) and some which are just a jumble of symbols with little meaning (i.e. func = (.) ((.) (+)) (*))
Maybe this will help. First let's write it without operator notation which might be confusing.
append :: [a] -> [a] -> [a]
append [] ys = ys
append (x:xs) ys = x : append xs ys
We can apply one argument at a time:
appendEmpty :: [a] -> [a]
appendEmpty = append []
we could equivalently could have written that
appendEmpty ys = ys
from the first equation.
If we apply a non-empty first argument:
-- Since 1 is an Int, the type gets specialized.
appendOne :: [Int] -> [Int]
appendOne = append (1:[])
we could have equivalently have written that
appendOne ys = 1 : append [] ys
from the second equation.
You are confused about how Function Currying works.
Consider the following function definitions of (++).
Takes two arguments, produces one list:
(++) :: [a] -> [a] -> [a]
[] ++ ys = ys
(x:xs) ++ ys = x : (xs ++ ys)
Takes one argument, produces a function taking one list and producing a list:
(++) :: [a] -> ([a] -> [a])
(++) [] = id
(++) (x:xs) = (x :) . (xs ++)
If you look closely, these functions will always produce the same output. By removing the second parameter, we have changed the return type from [a] to [a] -> [a].
If we supply two parameters to (++) we get a result of type [a]
If we supply only one parameter we get a result of type [a] -> [a]
This is called function currying. We don't need to provide all the arguments to a function with multiple arguments. If we supply fewer then the total number of arguments, instead of getting a "concrete" result ([a]) we get a function as a result which can take the remaining parameters ([a] -> [a]).
I have two functions f and g and I am trying to return f(g(x)) but I do not know the value of x and I am not really sure how to go about this.
A more concrete example: if I have functions f = x + 1 and g = x * 2 and I am trying to return f(g(x)) I should get a function equal to (x*2) + 1
It looks like you have it right, f(g(x)) should work fine. I'm not sure why you have a return keyword there (it's not a keyword in ocaml). Here is a correct version,
let compose f g x = f (g x)
The type definition for this is,
val compose : ('b -> 'c) -> ('a -> 'b) -> 'a -> 'c = <fun>
Each, 'a,'b,'c are abstract types; we don't care what they are, they just need to be consistent in the definition (so, the domain of g must be in the range of f).
let x_plus_x_plus_1 = compose (fun x -> x + 1) (fun x -> x * 2)