Haskell (.) for function with multiple operands - haskell

The (.) operator has the signature:
(.) :: (b -> c) -> (a -> b) -> a -> c
(.) f g x = f $ g x
This looks a bit similar to the composition function in primitive recursive functions with one g.
I'm not interested in extending the number of g-functions, but (a number of) functions that apply the (.) function on a function g with multiple operands. In other words something like:
(..) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
(..) f g x y = f $ g x y
A search on Hoogle doesn't result in any function. Is there a package that can handle this with an arbitrary number of operands?

To answer-ify my comments:
Multi-argument function composition operators are very easy to define, and luckily someone has done this for you already. The composition package has a nice set of operators for you to use to compose functions in this manner. I also find that instead of using haskell.org's hoogle engine, fpcomplete's version searches through more packages making it easier to find what I'm looking for.

Related

Haskell difference between function composition and bind

I can't understand the difference between Dot (function composition) and bind (>>=) .
If I understand, these two ways take the previous result of a function for a new function.
So what is the difference ?
They are pretty different. Let's look at their signatures:
(.) :: (b -> c) -> (a -> b) -> (a -> c)
(>>=) :: (Monad m) => m a -> (a -> m b) -> m b
As you said, the function composition is just a way to pass a result of one function as an argument to another one like this:
f = g . h
is equivalent to
f x = g (h x)
You can think about is as some kind of a "conveyor", where your value goes through several processing steps.
But (>>=) is quite different. It is related to such context as monad which is something like some value in some context (it's highly recommended to read the previous link if you aren't familiar with it).
So let x be some value in a context. Our context will be nullability (Maybe monad), and the value is 2. So, x = Just 2. We could, for example, get it as a result of a lookup from some associative container (such operation might fail, that's the reason why it is Maybe Int, but not Int).
Now we want to pass our x to some arithmetic function f that accepts just Int and may fail, so its signature looks like:
f :: Int -> Maybe Int
We can't just pass our value because of type mismatch. We could unpack x and handle some cases with if, but we could do that in almost all other languages. In haskell, we can use (>>=):
x >>= f
This allows as to chain the effects:
if x is Nothing, then the result is Nothing immediately
else x is unpacked and passed to f
This is a generalization of the operator ?., that you could see in some languages:
x = a?.func1()?.func2();
which checks for null at each "step" and stops immediately if hits null or returns the value in case of success. In haskell it looks like:
x = a >>= func1 >>= func2
However, bind with monads is a much more powerful concept, allowing you, for example, to emulate stateful computations in a language without mutability like haskell.
(>>=) is a form of function application.
(>>=) :: Monad m => m a -> (a -> m b) -> m b
flip ($) :: a -> (a -> b) -> b
It takes a value, but "extracts" part of it in order to apply the given function. Chaining two functions, like x >>= f >>= g requires the argument type of g to be different from (but at the same type similar to) the return type of f, unlike composition, which requires the types to match exactly.
Composed with return, it
really is just function application, but restricted to certain kinds of functions.
flip ($) :: a -> (a -> b) -> b
(>>=) . return :: Monad m => a -> (a -> m b) -> m b
(.) is more like (<=<) (from Control.Monad).
(.) :: (b -> c) -> (a -> b) -> a -> c
(<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c
But again, instead of simply passing the result of one function to another, it first "extracts" a value before doing application.

Is monad bind (>>=) operator closer to function composition (chaining) or function application?

In many articles I have read that monad >>= operator is a way to represent function composition. But for me it is closer to some kind of advanced function application
($) :: (a -> b) -> a -> b
(>>=) :: Monad m => m a -> (a -> m b) -> m b
For composition we have
(.) :: (b -> c) -> (a -> b) -> a -> c
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
Please clarify.
Clearly, >>= is not a way to represent function composition. Function composition is simply done with .. However, I don't think any of the articles you've read meant this, either.
What they meant was “upgrading” function composition to work directly with “monadic functions”, i.e. functions of the form a -> m b. The technical term for such functions is Kleisli arrows, and indeed they can be composed with <=< or >=>. (Alternatively, you can use the Category instance, then you can also compose them with . or >>>.)
However, talking about arrows / categories tends to be confusing especially to beginners, just like point-free definitions of ordinary functions are often confusing. Luckily, Haskell allows us to express functions also in a more familiar style that focuses on the results of functions, rather the functions themselves as abstract morphisms†. It's done with lambda abstraction: instead of
q = h . g . f
you may write
q = (\x -> (\y -> (\z -> h z) (g y)) (f x))
...of course the preferred style would be (this being only syntactic sugar for lambda abstraction!)&ddagger;
q x = let y = f x
z = g y
in h z
Note how, in the lambda expression, basically composition was replaced by application:
q = \x -> (\y -> (\z -> h z) $ g y) $ f x
Adapted to Kleisli arrows, this means instead of
q = h <=< g <=< f
you write
q = \x -> (\y -> (\z -> h z) =<< g y) =<< f x
which again looks of course much nicer with flipped operators or syntactic sugar:
q x = do y <- f x
z <- g y
h z
So, indeed, =<< is to <=< like $ is to .. The reason it still makes sense to call it a composition operator is that, apart from “applying to values”, the >>= operator also does the nontrivial bit about Kleisli arrow composition, which function composition doesn't need: joining the monadic layers.
†The reason this works is that Hask is a cartesian closed category, in particular a well-pointed category. In such a category, arrows can, broadly speaking, be defined by the collection of all their results when applied to simple argument values.
&ddagger;#adamse remarks that let is not really syntactic sugar for lambda abstraction. This is particularly relevant in case of recursive definitions, which you can't directly write with a lambda. But in simple cases like this here, let does behave like syntactic sugar for lambdas, just like do notation is syntactic sugar for lambdas and >>=. (BTW, there's an extension which allows recursion even in do notation... it circumvents the lambda-restriction by using fixed-point combinators.)
Just as an illustration, consider this:
($) :: (a -> b) -> a -> b
let g=g in (g $) :: a -> b
g :: (a -> b)
_____
Functor f => / \
(<$>) :: (a -> b) -> f a -> f b
let g=g in (g <$>) :: f a -> f b
g :: (a -> b)
___________________
Applicative f => / / \
(<*>) :: f (a -> b) -> f a -> f b
let h=h in (h <*>) :: f a -> f b
h :: f (a -> b)
_____________
Monad m => /.------. \
(=<<) :: (a -> m b) -> m a -> m b
let k=k in (k =<<) :: m a -> m b
k :: (a -> m b)
So yes, each one of those, (g <$>), (h <*>) or (k =<<), is some kind of a function application, promoted into either Functor, Applicative Functor, or a Monad "context". And (g $) is just a regular kind of application of a regular kind of function.
With Functors, functions have no influence on the f component of the overall thing. They work strictly on the inside and can't influence the "wrapping".
With Applicatives, the functions come wrapped in an f, which wrapping combines with that of an argument (as part of the application) to produce the wrapping of the result.
With Monads, functions themselves now produce the wrapped results, pulling their arguments somehow from the wrapped argument (as part of the application).
We can see the three operators as some kind of a marking on a function, like mathematicians like to write say f' or f^ or f* (and in the original work by Eugenio Moggi(1) f* is exactly what was used, denoting the promoted function (f =<<)).
And of course, with the promoted functions :: f a -> f b, we get to chain them, because now the types line up. The promotion is what allows the composition.
(1) "Notions of computation and monads", Eugenio Moggi, July 1991.
more about compositionality, with a picture: Monads with Join() instead of Bind()
So the functor is "magically working inside" "the pipes"; applicative is "prefabricated pipes built from components in advance"; and monads are "building pipe networks as we go". An illustration:

Returning a function in Haskell

In Haskell, is it possible to return a function from within a function? I tried searching on Hoogle for:
(a -> b) -> a -> b
but couldn't find any functions that could achieve this.
Yes, you can, and it's so common and deeply ingrained in the language that you don't even notice it!
For instance, when you write
mean :: Double -> Double -> Double
mean a b = (a + b) / 2
What you're really doing is, you define a function
mean :: Double -> EndoDouble
mean a = meanA
where meanA b = (a + b) / 2
where the type of meanA,
type EndoDouble = Double -> Double
happens to be a function type.
So, any "multi-parameter function" in Haskell really is a single-parameter function that returns a function! The concept is called Currying, you might have heard about it.
Treating functions as first-class citizens is one of the advantages of Haskell and doesn't require any special syntax.
For example if you want to have a function which will double the result of given function you can write:
doubleFunction f = (\x -> 2 * (f x))
When given a function f, doubleFunction is equal to a function which multiplies (f x) by 2. You can write it using function composition:
doubleFunction f = (* 2) . f
or even shorter:
doubleFunction = ((* 2) .)
doubleFunction is of type:
doubleFunction :: (Num a) => (a -> b) -> a -> b
Yes, you can: functions are values in Haskell, so it can be as simple as
functionIdentity :: (a -> b) -> a -> b
functionIdentity f = f
...which is just a specialised identity function.
You may also "explicitly" return a function by using a lambda if you wish, like const:
const x = \_ -> x

Taste of Haskell : definition of . (composition)

In this talk at 52:40 this slide below is discussed.
I don't quite understand this definition.
Why is the x needed in the definition ?
Why is the output not needed ?
For example why is the definition not (f . g) x -> y = f (g x) -> y or something like that ?
Is it easier to understand this definition if I look at it as a rewriting rule ? Whenever the expression evaluator encounters a pattern like on the left side it should rewrite it to the right side?
Is the rewriting rule interpretation the only correct way to understand this definition ? (This interpretation is the only way that this definition makes sense to me but I am not even sure if this is the correct way to interpret this definition.) I have to admit that I am quite a beginner in Haskell.
EDIT:
Or this definition is just a sugar for a lambda expression ?
Or the lambda expression is sugar for the rewriting rule ?
Composition can be written in several equivalent ways.
(.) = \f g -> \x -> f (g x)
(.) = \f g x -> f (g x)
f . g = \x -> f (g x)
The last example says "a composition of two functions gives a function, such that..."
More equivalent expressions:
(.) f g = \x -> f (g x)
(.) f g x = f (g x)
(f . g) x = f (g x)
Perhaps the infix notation is confusing you? Let's look at another way to write that definition:
(.) :: (b -> c) -> (a -> b) -> a -> c
(.) f g x = f (g x) -- definition 1
So we can think of (.) as a function which takes three parameters, f (a function), g (another function), and x (a value). It then returns f ( g x). To invoke this function, we could write an expression like:
(.) head tail "test"
which would return 'e'. However, functions with names beginning with certain special characters (like .) can be used infix style, like so:
(head . tail) "test"
Now, another way to define . is like this:
(f . g) x = f (g x) -- definition 2
This is identical to "definition 1", but the notation may look a little strange, with the function "name" . appearing after the first parameter! But this is just another example of infix notation.
Now, let's look at how this function is actually defined in Prelude:
(.) :: (b -> c) -> (a -> b) -> a -> c
(.) f g = \x -> f (g x)
This is equivalent to definitions 1 and 2, but uses a syntax you may not be familiar with, lambda notation. The right hand side introduces an unnamed function with a single parameter x, and defines that function to be f (g x). So the whole thing says that that the function (.) f g is defined to be that unnamed function! You may wonder why anyone would write this in such a strange way. It will make more sense when you've worked with infix notation and lambdas for a while.
-> is needed for the type definition of the function, i.e to say what types the functions take as arguments and what type has his result. Explanations:
f :: ... is something like "function f has type ...
(a -> b) means the type "a function which takes an argument of type a and returns an argument of type b"
(a -> b) -> (b->c) -> (a->c) means "a function which takes a function of type a->b and a function of type b->c and return a function of type a->c" (this is a simplified formulation. Please refer to the note below)
The second line the the definition of f.g. Its like defining functions in math. There you define a function h by saying what shall be result of h(x) for any given argument x (you can write h(x)=x² for example). You have read the line
(f . g) x = f (g x)
as
(f . g)(x) := f(g(x))
which shall be read as: "The result of the function f . g for any given x shall be f(g(x))"
Conclusion: -> is like the arrow in mathematics, which you might have seen in terms like f : R -> R and = is like := (f(x):=x² means in mathematics, that f(x) is defined to be x²)
Note: The actual type of (a -> b) -> (b->c) -> (a->c) is (as mentioned by #Ben Voigt): "function which takes a function of type a->b and returns a function which maps a function of type b->c onto ta function of type a->c". #jhegedus: Please let me note in the comments if you need explanation for it.
That's not the source code of (.), although it is close. Here's the actual source:
-- | Function composition.
{-# INLINE (.) #-}
-- Make sure it has TWO args only on the left, so that it inlines
-- when applied to two functions, even if there is no final argument
(.) :: (b -> c) -> (a -> b) -> a -> c
(.) f g = \x -> f (g x)
(f . g) is a function. The source uses a lambda form to be that function. A lambda form must provide local bindings for each of its arguments. In this case, there is only one argument, and it is locally bound to the name 'x'. That's why 'x' (which is of type 'a') must be mentioned.
Since it is marked INLINE, it will effectively rewrite the code during the optimizer passes. (IIRC, that's after desugaring (conversion to Core) and before conversion to STG.)
Lambdas are not sugar, they are fundamental. let/where are sugar for lambdas.
Function definitions are almost sugar for lambdas, but the optimizer (in GHC as least) uses the arity in the definition to determine when/how to inline a function. The type "(b -> c) -> (a -> b) -> a -> c" can be thought of as any arity from 0 to 3, and can be defined with any of those arities.
Unnecessary parentheses can be used to strongly hint at the arity you want to use, although the slide does that backwards from the convention I've seen. For example, adding parentheses around "a -> c" to get "(b -> c) -> (a -> b) -> (a -> c)"; that type is generally thought of a binary function type. The slides use that type, but then use a ternary definition.

Pointfree (or library) function for applying two functions to single input

I keep reusing lambda expressions such as
\x -> (f x, g x)
where I apply the same input to two functions and encapsulate the result in a pair. I can write a function capturing this
combine :: (a -> b) -> (a -> c) -> a -> (b,c)
combine f g x = (f x, g x)
Now the above lambda expression is just combine f g. I have two questions.
I'm interested to know if there is a standard library function that does this that I just can't find.
Out of curiosity, I'd like to rewrite this function in point-free style, but I'm having a lot of trouble with it.
Control.Arrow has the function (&&&) for this. It has a "more general" type, which unfortunately means that Hoogle doesn't find it (maybe this should be considered a bug in Hoogle?).
You can usually figure this sort of thing automatically with pointfree, which lambdabot in #haskell has as a plugin.
For example:
<shachaf> #pl combine f g x = (f x, g x)
<lambdabot> combine = liftM2 (,)
Where liftM2 with the (r ->) instance of Monad has type (a -> b -> c) -> (r -> a) -> (r -> b) -> r -> c. Of course, there are many other ways of writing this point-free, depending on what primitives you allow.
I'm interested to know if there is a standard library function that does this that I just can't find.
It's easy to miss because of the type class, but look at Control.Arrow. Plain Arrows can't be curried or applied, so the Arrow combinators are pointfree by necessity. If you specialize them to (->), you'll find the one you want is this:
(&&&) :: (Arrow a) => a b c -> a b c' -> a b (c, c')
There are other, similar functions, such as the equivalent operation for Either, which specialized to (->) looks like this:
(|||) :: (a -> c) -> (b -> c) -> Either a b -> c
Which is the same as either.
Out of curiosity, I'd like to rewrite this function in point-free style, but I'm having a lot of trouble with it.
Since you're duplicating an input, you need some way of doing that pointfree--the most common way is via the Applicative or Monad instance for (->), for example \f g -> (,) <$> f <*> g. This is essentially an implicit, inline Reader monad, and the argument being split up is the "environment" value. Using this approach, join f x becomes f x x, pure or return become const, fmap becomes (.), and (<*>) becomes the S combinator \f g x -> f x (g x).
There are actually quite a few ways of doing this. The most common way is to use the (&&&) function from Control.Arrow:
f &&& g
However, often you have more functions or need to pass the result to another function, in which case it is much more convenient to use applicative style. Then
uncurry (+) . (f &&& g)
becomes
liftA2 (+) f g
As noted this can be used with more than one function:
liftA3 zip3 f g h

Resources