I've been learning currying in Haskell and now trying to write the Haskell type signature of a function in curried form, whose uncurried form has an argument pair of type (x, y) and a value of type x as its result. I think the correct approach would be f :: (y,x) -> x, but I'm not sure. Is it correct, and if not, why?
You can let ghci do this for you.
> f = undefined :: (a, b) -> c
> :t curry f
curry f :: a -> b -> c
You can uncurry the result to get back the original type.
> :t uncurry (curry f)
uncurry (curry f) :: (a, b) -> c
The actual implementation of curry is, perhaps, more enlightening.
curry :: ((a, b) -> c) -> a -> b -> c
curry f = \x -> \y -> f (x, y)
If f expects a tuple, then curry f simply packages its two arguments into a tuple to pass to f.
Examples are hard to come by, as functions in Haskell are usually fully curried already. But we can explicitly uncurry a binary operator to construct an example.
> (+) 3 5
8
> f = uncurry (+)
> f (3, 5)
8
> (curry f) 3 5
8
As an aside, the type you suggested is what you would get by inserting a call to flip between currying and uncurrying a function:
> :t uncurry . flip . curry
uncurry . flip . curry :: ((b, a) -> c) -> (a, b) -> c
To see this in action, you'd have to pick a non-commutative operator, like (++).
> strconcat = uncurry (++)
> strconcat ("foo", "bar")
"foobar"
> (uncurry . flip . curry) strconcat ("foo", "bar")
"barfoo"
Just swapping the elements of the tuple is not currying. You have to get rid of the tuple altogether. You can do that by taking the first element of the tuple as argument and returning a function which takes the second element of the tuple and finally returns the result type. In your case the type would be f :: x -> (y -> x), these parenthesis are redundant, it is the same as f :: x -> y -> x. This is the curried form.
Related
nestedApply :: (Applicative f, Applicative g) => g (f (a -> b)) -> f a -> g (f b)
As the type indicates, how to get that (a->b) applied to that a in the context f?
Thanks for help.
This one of those cases where it's helpful to focus on types. I will try to keep it simple and explain the reasoning.
Let's start with describing the task. We have gfab :: g(f(a->b)) and fa :: f a, and we want to have g(f b).
gfab :: g (f (a -> b))
fa :: f a
??1 :: g (f b)
Since g is a functor, to obtain type g T we can start with a value ??2 of type g U and apply fmap to ??3 :: U -> T. In our case, we have T = f b, so we are looking for:
gfab :: g (f (a -> b))
fa :: f a
??2 :: g U
??3 :: U -> f b
??1 = fmap ??3 ??2 :: g (f b)
Now, it looks like we should pick ??2 = gfab. After all,that's the only value of type g Something we have. We obtain U = f (a -> b).
gfab :: g (f (a -> b))
fa :: f a
??3 :: f (a -> b) -> f b
??1 = fmap ??3 gfab :: g (f b)
Let's make ??3 into a lambda, \ (x :: f (a->b)) -> ??4 with ??4 :: f b. (The type of x can be omitted, but I decided to add it to explain what's going on)
gfab :: g (f (a -> b))
fa :: f a
??4 :: f b
??1 = fmap (\ (x :: f (a->b)) -> ??4) gfab :: g (f b)
How to craft ??4. Well, we have values of types f (a->b) and f a, so we can <*> those to get f b. We finally obtain:
gfab :: g (f (a -> b))
fa :: f a
??1 = fmap (\ (x :: f (a->b)) -> x <*> fa) gfab :: g (f b)
We can simplyfy that into:
nestedApply gfab fa = fmap (<*> fa) gfab
Now, this is not the most elegant way to do it, but understanding the process is important.
With
nestedApply :: (Applicative f, Applicative g)
=> g (f (a -> b))
-> f a
-> g (f b )
to get that (a->b) applied to that a in the context f, we need to operate in the context g.
And that's just fmap.
It's clearer with the flipped signature, focusing on its last part
flip nestedApply :: (Applicative f, Applicative g)
=> f a
-> g (f (a -> b)) --- from here
-> g (f b ) --- to here
So what we have here is
nestedApply gffun fx = fmap (bar fx) gffun
with bar fx being applied under the g wraps by fmap for us. Which is
bar fx :: f (a -> b)
-> f b
i.e.
bar :: f a
-> f (a -> b)
-> f b
and this is just <*> isn't it, again flipped. Thus we get the answer,
nestedApply gffun fx = fmap (<*> fx) gffun
As we can see only fmap capabilities of g are used, so we only need
nestedApply :: (Applicative f, Functor g) => ...
in the type signature.
It's easy when writing it on a sheet of paper, in 2D. Which we imitate here with the wild indentation to get that vertical alignment.
Yes we the humans learned to write first, on paper, and to type on a typewriter, much later. The last generation or two were forced into linear typing by the contemporary devices since the young age but now the scribbling and talking (and gesturing and pointing) will hopefully be taking over yet again. Inventive input modes will eventually include 3D workflows and that will be a definite advancement. 1D bad, 2D good, 3D even better. For instance many category theory diagrams are much easier to follow (and at least imagine) when drawn in 3D. The rule of thumb is, it should be easy, not hard. If it's too busy, it probably needs another dimension.
Just playing connect the wires under the wraps. A few self-evident diagrams, and it's done.
Here's some type mandalas for you (again, flipped):
-- <$> -- <*> -- =<<
f a f a f a
(a -> b) f (a -> b) (a -> f b)
f b f b f ( f b) -- fmapped, and
f b -- joined
and of course the mother of all applications,
-- $
a
a -> b
b
a.k.a. Modus Ponens (yes, also flipped).
I have the following two type signatures in Haskell:
foo :: (a -> (a,b)) -> a -> [b]
bar :: (a -> b) -> (a -> b -> c) -> a -> c
I want to write a concrete implementation of these two functions but I'm really struggling to understand where to start.
I understand that foo takes a function (a -> (a,b)) and returns a and a list containing b.
And bar takes a function (b -> c) which returns a function (a -> b -> c) which finally returns a and 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?
You have some misunderstandings there:
I understand that foo takes a function (a -> (a,b)) and returns a and a list containing b.
No, it doesn't return a. It expects it as another argument, in addition to that function.
And bar takes a function (b -> c) which returns a function (a -> b -> c) which finally returns a and c.
Same here. Given g :: a -> b, bar returns a function bar g :: (a -> b -> c) -> a -> c. This function, in turn, given a function h :: (a -> b -> c), returns a function of type a -> c. And so it goes.
It's just like playing with pieces of a puzzle:
foo :: (a -> (a,b)) -> a -> [b]
-- g :: a -> (a,b)
-- x :: a
-- g x :: (a,b)
foo g x = [b] where
(a,b) = g x
bar :: (a -> b) -> (a -> b -> c) -> a -> c
-- g :: a -> b
-- x :: a
-- g x :: b
-- h :: a -> b -> c
-- h x :: b -> c
-- h x (g x) :: c
bar g h x = c where
c = ....
There's not much free choice for us here. Although, there are more ways to get more values of type b, for foo. Instead of ignoring that a in (a,b) = g x, we can use it in more applications of g, so there actually are many more possibilities there, like
foo2 :: (a -> (a,b)) -> a -> [b]
foo2 g x = [b1,b2] where
(a1,b1) = g x
(a2,b2) = g a1
and many more. Still, the types guide the possible implementations. foo can even make use of foo in its implementation, according to the types:
foo3 :: (a -> (a,b)) -> a -> [b]
foo3 g x = b : bs where
(a,b) = g x
bs = ...
So now, with this implementation, the previous two become its special cases: foo g x === take 1 (foo3 g x) and foo2 g x === take 2 (foo3 g x). Having the most general definition is probably best.
In addition to #will-nes's answer, it will be useful to treat (->) as a right-associative infix operator. So something like f: a -> b -> c is the same as f: a -> (b -> c). So this is saying f is a function that takes a value of type a and returns you a value of type b -> c, which is, another function, one that takes a value of type b and returns you a value of type c.
So the types in your example can be re-written as follows
foo :: (a -> (a,b)) -> (a -> [b])
bar :: (a -> b) -> ((a -> (b -> c)) -> (a -> c))
Similarly, you can think of arguments to a function in pieces as well, as being left-associative (like + and -), though there's no explicit operator in this case. foo a b c d e is the same as ((((foo a) b) c) d) e. For example, let's say we have a function f: Int -> Int -> Int (which is the same as f: Int -> (Int -> Int)). You don't have to provide both arguments at once. So you can write g = f 1, which has the type (Int -> Int). And then you can provide an argument to g, like g 2, which has the type Int. f 1 2 and let g = f 1 in g 2 are more or less the same. Here's a more concrete example of how this works:
Prelude> f = (+)
Prelude> g = f 1
Prelude> g 2
3
Prelude> :t f
f :: Num a => a -> a -> a
Prelude> :t g
g :: Num a => a -> a
Prelude> :t g 2
g 2 :: Num a => a
In #will-nes's sample implementation examples, he defines the functions with all of the arguments up front, but you don't have to think of them that way. Just think of f: a -> b -> c as taking a value of type a and returning another function. While most of the methods you encounter will use all of their arguments up-front, there might be cases in which you don't want to do that. Here's an example:
veryExpensive :: A -> B
unstagedFun :: A -> (B -> C) -> C
unstagedFun a f = f (veryExpensive a)
stagedFun :: A -> (B -> C) -> C
stagedFun a = let b = veryExpensive a in \f -> f b
(You can also rewrite the latter as let b = veryExpensive a in ($ b))
Of course, with compiler optimizations, I wouldn't be surprised if the unstaged version staged automatically, but hopefully this offers some motivation for thinking of functions as not having multiple arguments, but rather, as a single argument, but they may return other functions that may themselves return functions (but also only take a single argument).
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]
I am trying to understand how fmap fmap applies to a function like say (*3).
The type of fmap fmap:
(fmap fmap):: (Functor f1, Functor f) => f (a -> b) -> f (f1 a -> f1 b)
Type of (*3):
(*3) :: Num a => a -> a
Which means that the signature a -> a corresponds to f (a -> b), right?
Prelude> :t (fmap fmap (*3))
(fmap fmap (*3)):: (Num (a -> b), Functor f) => (a -> b) -> f a -> f b
I have tried creating a simple test:
test :: (Functor f) => f (a -> b) -> Bool
test f = True
And feeding (*3) into it, but I get:
*Main> :t (test (*3))
<interactive>:1:8:
No instance for (Num (a0 -> b0)) arising from a use of ‘*’
In the first argument of ‘test’, namely ‘(* 3)’
In the expression: (test (* 3))
Why is that happening?
Polymorphism is dangerous when you do not know what you are doing. Both fmap and (*) are polymorphic functions and using them blindly can lead to very confusing (and possibly incorrect) code. I have answered a similar question before:
What is happening when I compose * with + in Haskell?
In such cases, I believe that looking at the types of values can help you figure out where you are going wrong and how to rectify the problem. Let's start with the type signature of fmap:
fmap :: Functor f => (a -> b) -> f a -> f b
|______| |________|
| |
domain codomain
The type signature of fmap is easy to understand. It lifts a function from a to b into the context of a functor, whatever that functor may be (e.g. list, maybe, either, etc.).
The words "domain" and "codomain" just mean "input" and "output" respectively. Anyway, let's see what happens when we apply fmap to fmap:
fmap :: Functor f => (a -> b) -> f a -> f b
|______|
|
fmap :: Functor g => (x -> y) -> g x -> g y
|______| |________|
| |
a -> b
As you can see, a := x -> y and b := g x -> g y. In addition, the Functor g constraint is added. This gives us the type signature of fmap fmap:
fmap fmap :: (Functor f, Functor g) => f (x -> y) -> f (g x -> g y)
So, what does fmap fmap do? The first fmap has lifted the second fmap into the context of a functor f. Let's say that f is Maybe. Hence, on specializing:
fmap fmap :: Functor g => Maybe (x -> y) -> Maybe (g x -> g y)
Hence fmap fmap must be applied to a Maybe value with a function inside it. What fmap fmap does is that it lifts the function inside the Maybe value into the context of another functor g. Let's say that g is []. Hence, on specializing:
fmap fmap :: Maybe (x -> y) -> Maybe ([x] -> [y])
If we apply fmap fmap to Nothing then we get Nothing. However, if we apply it to Just (+1) then we get a function that increments every number of a list, wrapped in a Just constructor (i.e. we get Just (fmap (+1))).
However, fmap fmap is more general. What it actually does it that it looks inside a functor f (whatever f may be) and lifts the function(s) inside f into the context of another functor g.
So far so good. So what's the problem? The problem is when you apply fmap fmap to (*3). This is stupid and dangerous, like drinking and driving. Let me tell you why it's stupid and dangerous. Take a look at the type signature of (*3):
(*3) :: Num a => a -> a
When you apply fmap fmap to (*3) then the functor f is specialized to (->) r (i.e. a function). A function is a valid functor. The fmap function for (->) r is simply function composition. Hence, the type of fmap fmap on specializing is:
fmap fmap :: Functor g => (r -> x -> y) -> r -> g x -> g y
-- or
(.) fmap :: Functor g => (r -> x -> y) -> r -> g x -> g y
|___________|
|
(*3) :: Num a => a -> a
| |
| ------
| | |
r -> x -> y
Do you see why it's stupid and dangerous?
It's stupid because you are applying a function which expects an input function with two arguments (r -> x -> y) to a function with only one argument, (*3) :: Num a => a -> a.
It's dangerous because the output of (*3) is polymorphic. Hence, the compiler doesn't tell you that you are doing something stupid. Luckily, because the output is bounded you get a type constraint Num (x -> y) which should indicate that you have gone wrong somewhere.
Working out the types, r := a := x -> y. Hence, we get the following type signature:
fmap . (*3) :: (Num (x -> y), Functor g) => (x -> y) -> g x -> g y
Let me show you why it's wrong using values:
fmap . (*3)
= \x -> fmap (x * 3)
|_____|
|
+--> You are trying to lift a number into the context of a functor!
What you really want to do is apply fmap fmap to (*), which is a binary function:
(.) fmap :: Functor g => (r -> x -> y) -> r -> g x -> g y
|___________|
|
(*) :: Num a => a -> a -> a
| | |
r -> x -> y
Hence, r := x := y := a. This gives you the type signature:
fmap . (*) :: (Num a, Functor g) => a -> g a -> g a
This makes even more sense when you see the values:
fmap . (*)
= \x -> fmap (x *)
Hence, fmap fmap (*) 3 is simply fmap (3*).
Finally, you have the same problem with your test function:
test :: Functor f => f (a -> b) -> Bool
On specializing functor f to (->) r we get:
test :: (r -> a -> b) -> Bool
|___________|
|
(*3) :: Num x => x -> x
| |
| ------
| | |
r -> a -> b
Hence, r := x := a -> b. Thus we get type signature:
test (*3) :: Num (a -> b) => Bool
Since neither a nor b appear in the output type, the constraint Num (a -> b) must be resolved immediately. If a or b appeared in the output type then they could be specialized and a different instance of Num (a -> b) could be chosen. However, because they don't appear in the output type the compiler has to decide which instance of Num (a -> b) to choose immediately; and because Num (a -> b) is a stupid constraint which doesn't have any instance, the compiler throws an error.
If you try test (*) then you won't get any error, for the same reason that I mentioned above.
The problem I have been given says this:
In a similar way to mapMaybe, define
the function:
composeMaybe :: (a->Maybe b) -> (b -> Maybe c) -> (a-> Maybe c)
which composes two error-raising functions.
The type Maybe a and the function mapMaybe are coded like this:
data Maybe a = Nothing | Just a
mapMaybe g Nothing = Nothing
mapMaybe g (Just x) = Just (g x)
I tried using composition like this:
composeMaybe f g = f.g
But it does not compile.
Could anyone point me in the right direction?
The tool you are looking for already exists. There are two Kleisli composition operators in Control.Monad.
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
(<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c
When m = Maybe, the implementation of composeMaybe becomes apparent:
composeMaybe = (>=>)
Looking at the definition of (>=>),
f >=> g = \x -> f x >>= g
which you can inline if you want to think about it in your own terms as
composeMaybe f g x = f x >>= g
or which could be written in do-sugar as:
composeMaybe f g x = do
y <- f x
g y
In general, I'd just stick to using (>=>), which has nice theoretical reasons for existing, because it provides the cleanest way to state the monad laws.
First of all: if anything it should be g.f, not f.g because you want a function which takes the same argument as f and gives the same return value as g. However that doesn't work because the return type of f does not equal the argument type of g (the return type of f has a Maybe in it and the argument type of g does not).
So what you need to do is: Define a function which takes a Maybe b as an argument. If that argument is Nothing, it should return Nothing. If the argument is Just b, it should return g b. composeMaybe should return the composition of the function with f.
Here is an excellent tutorial about Haskell monads (and especially the Maybe monad, which is used in the first examples).
composeMaybe :: (a -> Maybe b)
-> (b -> Maybe c)
-> (a -> Maybe c)
composeMaybe f g = \x ->
Since g takes an argument of type b, but f produces a value of type Maybe b, you have to pattern match on the result of f x if you want to pass that result to g.
case f x of
Nothing -> ...
Just y -> ...
A very similar function already exists — the monadic bind operator, >>=. Its type (for the Maybe monad) is Maybe a -> (a -> Maybe b) -> Maybe b, and it's used like this:
Just 100 >>= \n -> Just (show n) -- gives Just "100"
It's not exactly the same as your composeMaybe function, which takes a function returning a Maybe instead of a direct Maybe value for its first argument. But you can write your composeMaybe function very simply with this operator — it's almost as simple as the definition of the normal compose function, (.) f g x = f (g x).
Notice how close the types of composeMaybe's arguments are to what the monadic bind operator wants for its latter argument:
ghci> :t (>>=)
(>>=) :: (Monad m) => m a -> (a -> m b) -> m b
The order of f and g is backward for composition, so how about a better name?
thenMaybe :: (a -> Maybe b) -> (b -> Maybe c) -> (a -> Maybe c)
thenMaybe f g = (>>= g) . (>>= f) . return
Given the following definitions
times3 x = Just $ x * 3
saferecip x
| x == 0 = Nothing
| otherwise = Just $ 1 / x
one can, for example,
ghci> saferecip `thenMaybe` times3 $ 4
Just 0.75
ghci> saferecip `thenMaybe` times3 $ 8
Just 0.375
ghci> saferecip `thenMaybe` times3 $ 0
Nothing
ghci> times3 `thenMaybe` saferecip $ 0
Nothing
ghci> times3 `thenMaybe` saferecip $ 1
Just 0.3333333333333333