I have the following type signature in Haskell:
hi :: (b -> c) -> (a -> b) -> (a -> c)
I want to write a concrete implementation of it but I'm really struggling to understand where to start. I understand that hi takes a function (b -> c) which returns a function (a ->b) which finally returns a function (a -> c).
Can anyone show me an example of a concrete implementation? How do I know where to start with something like this and what goes on the left side of the definition?
One way to think of this is as a function that takes a (b -> c) and an (a -> b) and returns another function (a -> c). So let's start with that
hi f g = undefined -- f :: b -> c, g :: a -> b
We know that the return type has to be a function (a -> c) -
hi f g = \a -> undefined -- f :: b -> c, g :: a -> b
We now have something of type a on the right hand side, and we have a function g :: a -> b so a sensible thing to do (in fact, the only thing we can do) is to apply g to a
hi f g = \a -> g a -- ok, this fails to typecheck...
The expression g a has type b, and f :: b -> c, and we want to end up with a c. So again, there's only one thing we can do -
hi f g = \a -> f (g a)
And this type checks! We now start the process of cleaning up. We could move the a to the left of the equality sign
hi f g a = f (g a)
And, if you happen to know about the composition operator . you could notice that it can be used here
hi f g a = (f . g) a
Now the a is redundant on both sides (this is called eta reduction)
hi f g = f . g
and we can pull the . operator to the front of the expression by using its function form (.)
hi f g = (.) f g
Now the g and the f are both redundant (two more applications of eta reduction)
hi = (.)
So your function hi is nothing more than function composition.
You read it wrong: The -> operator is right-associative. Thus, your signature is: (b->c) -> ((a->b) -> (a->c)). So you can read it as : given a function from b to c, it returns a function that takes a function from a to b to finally returns a function from a to c.
From there, you should be able to resolve the exercise by yourself.
Related
I struggle to understand how type declarations work...
Like these ones for example:
t :: (a -> b) -> (b -> c) -> a -> c
s :: (a -> b -> c) -> (a -> b) -> a -> c
I know from just trying different things that the correct functions would look like this:
t :: (a -> b) -> (b -> c) -> a -> c
t f g x = g (f x)
s :: (a -> b -> c) -> (a -> b) -> a -> c
s f g x = f x (g x)
But how does this work? Why are the brackets at the end? Why is it not
t f g x = (f x) g
or
s f g x = (f x) g x
Im so lost
For the first example:
t :: (a -> b) -> (b -> c) -> a -> c
In a type declaration, the type1 -> type2 pattern indicates a function from type1 to type2. In type declarations, the -> operator is right-associative, so this is parsed as:
t :: (a -> b) -> ((b -> c) -> (a -> c))
This kind of construction is called "currying": providing the first argument (type a -> b) yields a function which accepts the second argument (type b -> c) which yields a function which accepts the third argument (type a).
The function declaration syntax is set up to do this automatically. The first two arguments are functions and the third is just a, so start with names that reflect that: f :: a -> b and g :: b -> c are functions, while x :: a is a fully generic type which could be anything.
t f g x = ...
Note that function application in Haskell is just concatenation: to apply function f to value x, just use f x. This syntax is left-associative, so t f g x is parsed as (((t f) g) x) to match the currying construction described above.
Anyway, given these types, you don't have much choice in how to put them together:
the only thing you know about the type a is that it's the type of x, and the argument type of f, so the only thing you can do with them is to apply the function to the value: f x.
the only thing you know about the type b is that it's the result type of f and the argument type of g, so the only thing you can do is apply g (f x).
the only thing you know about the type c is that it's the result type of g and of the overall function t, so the only thing t can return is g (f x).
The reason you can't do (f x) g is that the types don't match:
f :: a -> b
x :: a
(f x) :: b
g :: b -> c
So, you can apply g :: b -> c to (f x) :: b to get a result of type c. But not the other way around, because b might not even be a function type.
Im trying to wrap my head around Haskell and I'm having trouble trying to implement the following signature as a function. Could you guys give me an example using lambda expressions?
(b -> c) -> (a -> b) -> a -> c
Try with simpler examples first. For example,
f :: a -> a
f = ...
Since f is a function of one argument, we can extend this without thinking much into:
f :: a -> a
f = \x -> ...
Picking a return value for this function, we have exactly one good candidate, x, so:
f :: a -> a
f = \x -> x
although we could also have picked undefined or error "meh", or f x, which are less useful.
Here's another simple example:
g :: (a, b) -> (b, a)
g = ...
The only pattern that matches the function's input is a pair, so:
g :: (a, b) -> (b, a)
g = \(x, y) -> ...
This doesn't have to be equivalent to swap, but it's a good candidate because it terminates.
A last example that is more complicated:
h :: ((a, b) -> c) -> a -> b -> c
h = ...
This is a function of three arguments of types (a, b) -> c, a and b, so without thinking much we can extend the answer partially:
h :: ((a, b) -> c) -> a -> b -> c
h = \f -> \x -> \y -> ...
h = \f x y -> ...
(The lower line is just a convenient way to stack curried arguments.)
Now, I gave them names f, x and y because I think f is a good, generic name for a value that contains an ->, and x and y are good, generic names for arbitrary values. I could also have picked a and b to strengthen the connection between the types of the same name, but it'd also be a little confusing. So here, x :: a and y :: b.
As for filling out the function body, I can either go by asking "How do I apply the things I've got so the types align", or I can look at the return type, c, and look at what I have available to make a value of type c. f returns c if I feed it a pair of type (a, b). I have an x :: a and a y :: b, so (x, y) :: (a, b):
h :: ((a, b) -> c) -> a -> b -> c
h = \f x y -> f (x, y)
This is incidentally curry. I don't think you can find any other solution that terminates?
For simple functions there is often only one good candidate. When you have type signatures with multiple values of the same type, you have to consider what happens if you pick one over the other. The first case I can think of is when you implement the >>= operator for the state monad.
Let's rename our type variables:
a becomes oil
b becomes petrol
c becomes co₂
Now, you already recognised what the arguments to your function are:
implementation (x :: petrol -> co₂)
(y :: oil -> petrol)
(z :: oil)
= (? :: co₂)
It's sort of conventional to name functions f, g... and values a, b... _if we know nothing about the underlying types. Ok, but after we named the types, let's pick appropriate names accordingly:
implementation (car :: petrol -> co₂)
(refinery :: oil -> petrol)
(tankship :: oil)
= (? :: co₂)
Or, in lambda form without the local signatures:
implementation = \car refinery tankship -> ?
I'll leave the rest to you.
Can someone help me with writing my own version of a (.) function in Haskell?
From this post Haskell write your version of a ($) function I know how to determine a type of this function, but I still have the problem with its body.
I also do not know why ghci refuses to use the name (..).
($$$) :: (b -> c) -> (a -> b) -> a -> c
($$$) f (g x) = ((f g) $) x
infixr 9 $$$
Another idea of mine was for instance this one:
($$$) :: (b -> c) -> (a -> b) -> a -> c
($$$) f (g x) = map (f) (g x)
infixr 9 $$$
The error message says that "Parse error in pattern: g".
From the signature:
($$$) :: (b -> c) -> (a -> b) -> a -> c
your function needs 3 arguments. So I would start:
($$$) f g x = ...
| | \
| \ a
| \
| a->b
b->c
Update
This attempt at defining ($$$) does not work:
($$$) (f g) x = ...
It says that ($$$) takes two arguments. The way I've started to define ($$$) says that the function takes three arguments.
Are you coming from Lisp? You still seem to assume lists everywhere...
As I already said in the other thread, lists have nothing to do with this task, so neither of (:), foldr or map can possibly be useful here.
More to the point, the occurence of (g x) in the left-hand side of the definition doesn't make sense. (This is not a list, but apparently you think it should be a kind of “argument list”).
As a matter of fact, you could define ($$$) in un-curried form this way:
($$$) :: (b->c) -> (a->b, a) -> c
($$$) f (g, x) = ...
...which is exactly the same thing as the more elegant
f $$$ (g, x) = ...
In this case, you have an argument tuple (g, x), which is more or less equivalent to a Lisp list.
In Haskell, we like to write functions curried though. The signature
($$$) :: (b -> c) -> (a -> b) -> a -> c
is in fact parsed as
($$$) :: (b -> c) -> ( (a -> b) -> (a -> c) )
Hence the way to define such a function is, at the most fundamental level
($$$) = \f -> (\g -> (\x -> ... ))
Which can be written short as
($$$) f g x = ...
or
(f $$$ g) x = ...
In the actual definition part, you should similarly get the grasp of how things are actually parsed. As you have by now figured out, the composition operator can be defined as
($$$) f g x = f(g(x))
In fact, only the outer parentheses are necessary here: the preferred form is
($$$) f g x = f (g x)
or indeed
($$$) f g x = f $ g x
If something like g x or (f g) appears on its own in an expression, it always means that the left function is applied to the right argument. For f g this doesn't make sense, because though f is a function it can not take another function as its argument, only the result of such a function. Well, to get such a result you need to apply g to an argument!
Many thanks for your patience. I used brackets where I should not have. I still have problems with looking at everything (including mathematical operators) as a function. Now the idea of (.) is clear.
($$$) :: (b -> c) -> (a -> b) -> a -> c
($$$) f g x = f(g x)
infixr 9 $$$
Ordinary function composition is of the type
(.) :: (b -> c) -> (a -> b) -> a -> c
I figure this should generalize to types like:
(.) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
A concrete example: calculating difference-squared. We could write diffsq a b = (a - b) ^ 2, but it feels like I should be able to compose the (-) and (^2) to write something like diffsq = (^2) . (-).
I can't, of course. One thing I can do is use a tuple instead of two arguments to (-), by transforming it with uncurry, but this isn't the same.
Is it possible to do what I want? If not, what am I misunderstanding that makes me think it should be possible?
Note: This has effectively already been asked here, but the answer (that I suspect must exist) was not given.
My preferred implementation for this is
fmap . fmap :: (Functor f, Functor f1) => (a -> b) -> f (f1 a) -> f (f1 b)
If only because it is fairly easy to remember.
When instantiating f and f1 to (->) c and (->) d respectively you get the type
(a -> b) -> (c -> d -> a) -> c -> d -> b
which is the type of
(.) . (.) :: (b -> c) -> (a -> a1 -> b) -> a -> a1 -> c
but it is a bit easier to rattle off the fmap . fmap version and it generalizes to other functors.
Sometimes this is written fmap fmap fmap, but written as fmap . fmap it can be more readily expanded to allow more arguments.
fmap . fmap . fmap
:: (Functor f, Functor g, Functor h) => (a -> b) -> f (g (h a)) -> f (g (h b))
fmap . fmap . fmap . fmap
:: (Functor f, Functor g, Functor h, Functor i) => (a -> b) -> f (g (h (i a))) -> f (g (h (i b))
etc.
In general fmap composed with itself n times can be used to fmap n levels deep!
And since functions form a Functor, this provides plumbing for n arguments.
For more information, see Conal Elliott's Semantic Editor Combinators.
The misunderstanding is that you think of a function of type a -> b -> c as a function of two arguments with return type c, whereas it is in fact a function of one argument with return type b -> c because the function type associates to the right (i.e. it's the same as a -> (b -> c). This makes it impossible to use the standard function composition operator.
To see why, try applying the (.) operator which is of type (y -> z) -> (x -> y) -> (x -> z) operator to two functions, g :: c -> d and f :: a -> (b -> c). This means that we must unify y with c and also with b -> c. This doesn't make much sense. How can y be both c and a function returning c? That would have to be an infinite type. So this does not work.
Just because we can't use the standard composition operator, it doesn't stop us from defining our own.
compose2 :: (c -> d) -> (a -> b -> c) -> a -> b -> d
compose2 g f x y = g (f x y)
diffsq = (^2) `compose2` (-)
Usually it is better to avoid using point-free style in this case and just go with
diffsq a b = (a-b)^2
I don't know of a standard library function that does this, but the point-free pattern that accomplishes it is to compose the composition function:
(.) . (.) :: (b -> c) -> (a -> a1 -> b) -> a -> a1 -> c
I was going to write this in a comment, but it's a little long, and it draws from both mightybyte and hammar.
I suggest we standardize around operators such as .* for compose2 and .** for compose3. Using mightybyte's definition:
(.*) :: (c -> d) -> (a -> b -> c) -> (a -> b -> d)
(.*) = (.) . (.)
(.**) :: (d -> e) -> (a -> b -> c -> d) -> (a -> b -> c -> e)
(.**) = (.) . (.*)
diffsq :: (Num a) => a -> a -> a
diffsq = (^2) .* (-)
modminus :: (Integral a) => a -> a -> a -> a
modminus n = (`mod` n) .* (-)
diffsqmod :: (Integral a) => a -> a -> a -> a
diffsqmod = (^2) .** modminus
Yes, modminus and diffsqmod are very random and worthless functions, but they were quick and show the point. Notice how eerily easy it is to define the next level by composing in another compose function (similar to the chaining fmaps mentioned by Edward).
(.***) = (.) . (.**)
On a practical note, from compose12 upwards it is shorter to write the function name rather than the operator
f .*********** g
f `compose12` g
Though counting asterisks is tiring so we may want to stop the convention at 4 or 5 .
[edit] Another random idea, we could use .: for compose2, .:. for compose3, .:: for compose4, .::. for compose5, .::: for compose6, letting the number of dots (after the initial one) visually mark how many arguments to drill down. I think I like the stars better though.
As Max pointed out in a comment:
diffsq = ((^ 2) .) . (-)
You can think of f . g as applying one argument to g, then passing the result to f. (f .) . g applies two arguments to g, then passes the result to f. ((f .) .) . g applies three arguments to g, and so on.
\f g -> (f .) . g :: (c -> d) -> (a -> b -> c) -> a -> b -> d
If we left-section the composition operator with some function f :: c -> d (partial application with f on the left), we get:
(f .) :: (b -> c) -> b -> d
So we have this new function which expects a function from b -> c, but our g is a -> b -> c, or equivalently, a -> (b -> c). We need to apply an a before we can get what we need. Well, let's iterate once more:
((f .) .) :: (a -> b -> c) -> a -> b -> d
Here's what I think is an elegant way to achieve what you want. The Functor type class gives a way to 'push' a function down into a container so you can apply it to each element using fmap. You can think of a function a -> b as a container of bs with each element indexed by an element of a. So it's natural to make this instance:
instance Functor ((->) a) where
fmap f g = f . g
(I think you can get that by importing a suitable library but I can't remember which.)
Now the usual composition of f with g is trivially an fmap:
o1 :: (c -> d) -> (b -> c) -> (b -> d)
f `o1` g = fmap f g
A function of type a -> b -> c is a container of containers of elements of type c. So we just need to push our function f down twice. Here you go:
o2 :: (c -> d) -> (a -> (b -> c)) -> a -> (b -> d)
f `o2` g = fmap (fmap f) g
In practice you might find you don't need o1 or o2, just fmap. And if you can find the library whose location I've forgotten, you may find you can just use fmap without writ
ing any additional code.
I'm just learning Haskell and functional programming using Richard Bird's book and came across the type signature of the (.) function. Namely
(.) :: (b -> c) -> (a -> b) -> (a -> c)
and the associated definition
(f . g) x = f (g x)
I understand what the operator is doing but am a bit confused about how to read the type signature. Is it saying that (.) takes as its first argument a function of type (b -> c), then returns a function of type (a -> b), and finally returns a function of type (a -> c)? Is this the right way to read the type signature?
Also, could this be an example of currying, where (.) is a curried function that takes two parameters? Or is that not the correct way to think about currying?
You've almost got it, it takes a b -> c and returns a function (a -> b) -> (a -> c) which, when given an (a -> b) returns a function a -> c. It may also be helpful to know that in Haskell, you can wrap an operator in parens and use it prefix so
f . g === (.) f g
Now it's easier to see the currying
((.) f) g === f . g
Finally, notice that this type signature is equivalent to
(b -> c) -> (a -> b) -> a -> c
Since -> is right associative.
You can read function signatures with several arguments like this:
(.) :: (b -> c) -> ((a -> b) -> (a -> c))
so, (f .) :: (a -> b) -> (a -> c)
Next is the same:
foo :: a -> b -> c -> d -> e
foo :: a ->(b ->(c ->(d -> e)))
Function (.) takes 2 functions (a -> b) as a parameters and return their composition