when to use and when not to use pointfree style in haskell? - function

I just learned about pointfree style in Haskell and how it can help tidy up the code and make it easier to read. But sometimes they can make the code a bit too terse.
So, when I should I always use pointfree style and at what scenarios should I absolutely avoid pointfree style in Haskell?

As already commented, it's a matter of taste and there will always be edge cases where both styles are equally suited (or, indeed, a partially-pointed version is best). However, there are some cases where it's clear enough:
If a pointed expression can be η-reduced just like that, it's usually a good idea to do it.
f x = g (h x)
should better be written
f = g . h
If you want to memoise some computation before accepting some function parameters, you must keep these parameters out of the scope. For instance,
linRegression :: [(Double, Double)] -> Double -> Double
linRegression ps x = a * x + b
where a, b = -- expensive calculation of regression coefficients,
-- depending on the `ps`
isn't optimal performance-wise, because the coefficients will need to be recomputed for every x value received. If you make it point-free:
linRegression :: [(Double, Double)] -> Double -> Double
linRegression ps = (+b) . (a*)
where a, b = ...
this problem doesn't arise. (Perhaps GHC will in some cases figure this out by itself, but I wouldn't rely on it.)
Often though, it is better to make it pointed nevertheless, just not with an x in the same scope as a and b but bound by a dedicated lambda:
linRegression :: [(Double, Double)] -> Double -> Double
linRegression ps = \x -> a * x + b
where a, b = ...
If the point-free version is actually longer than the pointed version, I wouldn't use it. If you need to introduce tricks to get it point-free like flip and the Monad (a->) instance and this doesn't even make it shorter, then it will almost certainly be less readable than the pointed version.

My favorite answer comes from Richard Bird's Thinking Functionally with Haskell: pointfree style helps you reason about function composition while a pointed style helps you reason about function application.
If you find that a pointfree style is awkward for writing a particular function then you generally have two options:
Use a pointed style instead. Sometimes you do want to reason about application.
Redesign your function to be compositional in nature.
In my own programs, I've found that (2) often leads to a better design and that this design can then be more clearly expressed using a pointfree style. Pointfree style is not an end goal: it is a means to achieving a more compositional design.

Related

Universal Quantification in Isabelle/HOL

It has come to my attention that there are several ways to deal with universal quantification when working with Isabelle/HOL Isar. I am trying to write some proofs in a style that is suitable for undergraduate students to understand and reproduce (that's why I'm using Isar!) and I am confused about how to express universal quantification in a nice way.
In Coq for example, I can write forall x, P(x) and then I may say "induction x" and that will automatically generate goals according to the corresponding induction principle. However, in Isabelle/HOL Isar, if I want to directly apply an induction principle I must state the theorem without any quantification, like this:
lemma foo: P(x)
proof (induct x)
And this works fine as x is then treated as a schematic variable, as if it was universally quantified. However, it lacks the universal quantification in the statement which is not very educational. Another way I have fund is by using \<And> and \<forall>. However, I can not directly apply the induction principle if I state the lemma in this way, I have to first fix the universally quantified variables... which again seems inconvenient from an educational point of view:
lemma foo: \<And>x. P(x)
proof -
fix x
show "P(x)"
proof (induct x)
What is a nice proof pattern for expressing universal quantification that does not require me to explicitly fix variables before induction?
You can use induct_tac, case_tac, etc. These are the legacy variant of the induct/induction and cases methods used in proper Isar. They can operate on bound meta-universally-quantified variables in the goal state, like the x in your second example:
lemma foo: "⋀x. P(x :: nat)"
proof (induct_tac x)
One disadvantage of induct_tac over induction is that it does not provide cases, so you cannot just write case (Suc x) and then from Suc.IH and show ?case in your proof. Another disadvantage is that addressing bound variables is, in general, rather fragile, since their names are often generated automatically by Isabelle and may change when Isabelle changes. (not in the case you have shown above, of course)
This is one of the reasons why Isar proofs are preferred these days. I would strongly advise against showing your students ‘bad’ Isabelle with the intention that it is easier for them to understand.
The facts are these: free variables in a theorem statement in Isabelle are logically equivalent to universally-quantified variables and Isabelle automatically converts them to schematic variables after you have proven it. This convention is not unique to Isabelle; it is common in mathematics and logic, and it helps to reduce clutter. Isar in particular tries to avoid explicit use of the ⋀ operator in goal statements (i.e. have/show; they still appear in assume).
Or, in short: free variables in theorems are universally quantified by default. I doubt that students will find this hard to understand; I certainly did not when I started with Isabelle as a BSc student. In fact, I found it much more natural to state a theorem as xs # (ys # zs) = (xs # ys) # zs instead of ∀xs ys zs. xs # (ys # zs) = (xs # ys) # zs.

Advantage of Arrows over Functions

What is the advantage of arrows over regular functions in haskell. What can they do the functions can't. Functions can map over structures using fmap.
On more of a broad picture, arrows get you out of Hask and into other categories there are to explore. The Kleisli category is probably the best-acquainted to Haskellers, followed by Cokleisli. Those are the natural "extensions" of Hask: add an endofunctor around either the result or argument, then you get a category again if
Kleisli: the functor is a monad, so id ≅ return :: a -> m a
(.) ≅ (<=<) :: (b->m c) -> (a->m b) -> a->m c
CoKleisli: the functor is a comonad, so id ≅ coreturn :: m a -> a and
(.) :: (m b->c) -> (m a->b) -> m a->c
(For that you don't need Arrow yet, only Category. But general categories aren't very interesting, you normally want monoidal or even cartesian closed categories, which is what Arrow is roughly aiming at.)
But there are sure are lots of other categories. Most don't have much to do with Hask and can't be expressed with the standard Arrow class, mainly because the objects have special properties that not every Haskell type fulfills. Actually, if you add the ability to constrain the object types, the possibilities immediately become much wider. But even if you stay with the standard classes, perhaps even simply in ->, the point-free composition-style that is natural with arrows often comes out very nice, concise, and opens up new ways to think about transformations.
Functions are only an instance of arrows, it's like asking "Why use monads instead of just Maybe".
Anything you can do with arrows can of course be done with functions since the Arrow (->) instance can only talk about one small part of functions, namely what's in the Arrow type class. However, arrows has more instances than just plain functions, so we can use the ssame functions to operate on more complex types.
Arrows are nice since they can have a lot more structure than just a function, when traversing with just fmap, we have no way to accumulate effects, are more expressive than monads! Consider the Kleisli arrow,
newtype Kleisli m a b = Kleisli {runKleisli :: a -> m b}
This forms an arrow when m is a monad. So every Monad forms an arrow and thus we can build up monadic computations by seamlessly composing a -> m b's and do all sorts of useful things like this. Some XML libraries use arrows to abstract over functions from an element to it's subelements and use this to traverse over the document. Other parsers use arrows (their original purpose) though nowadays this seems to be falling out of favor for Applicative.
The point that you've hopefully noticed is that arrows are more generic, when we just talk about arrows, we avoid duplicating all the code that we would need to write to do something with our parsers, xml scrapers, and monadic functions!
It's just the same as opting for Monad over Maybe, we lose some power since we're no longer able to make specific statements, but we get more generic code in return.

Function equality on restricted functions

I already posted a question about function equality. It quickly concluded that general function equality is an incredibly hard problem and might be mathematically disprovable.
I would like to stub up a function
function equal(f, g, domain) {
}
f & g are halting functions that take one argument. Their argument is an natural number. These functions will return a boolean.
If no domain is passed then you may assume the domain defaults to all natural numbers.
The structure of domain is whatever is most convenient for the equal function.
Another important fact is that f & g are deterministic. and will consistantly return the same boolean m for f(n).
You may assume that f and g always return and don't throw any exceptions or crash due to errors as long as their input is within the domain
The question is language-agnostic and Asking for an implementation of the equal function. i'm not certain whether SO is the right place for this anymore.
f & g have no side-effects. and the domain does not have to be finite.
It's still not possible.
You could test both functions for some finite number of inputs and check them for equality on those inputs. If they are unequal for any input then the two functions are not identical. If they are equal in every case you tested then there is a reasonable chance that they are the same function, but you can't be completely certain.
In general it is infeasible to test every possible input unless the domain is small. If the domain is a 32 bit integer and your function is quite fast to evaluate then it might be feasible to check every possible input.
I believe the following to be the best you can do without doing static analysis on the source code:
function equal(f, g, domain) {
var n;
for (n in domain) {
if (f(domain[n]) != g(domain[n])) return false;
}
return true;
}
Note that this assumes the domain to be finite.
If the domain is not finite, Rice's theorem prevents such an algorithm from existing:
If we let f and g be the implementations and F and G be the mathematical functions these implementations calculate the values of, then it's Rice's theorem says that it's impossible to determine if f calculates G or g calculates F, as these are non-trivial properties of the implementations.
For further detail, see my answer to the previous question.
Depending on your use-case, you might be able to do some assumptions about f & g . Maybe in your case, they apply under specific conditions what might make it solvable.
In other cases, the only thing what I might recommend is fuzzy testing , on Abstract Syntax Tree or other representation.

Higher Order Function

I am having trouble understanding what my lecturer want me to do from this question. Can anyone help explain to me what he wants me to do?
Define a higher order version of the insertion sort algorithm. That is define
functions
insertBy :: Ord b => (a->b) -> a -> [a] -> [a]
inssortBy :: Ord b => (a->b) -> [a] -> [a]
and this bit is where it got me confused:
such that inssort f l sorts the list l such that an element x comes before an elementyif f x < f y.
If you were sorting numbers, then it's clear what x < y means. But what if you were sorting letters? Or customers? Or anything else without a clear (to the computer) ordering?
So you are supposed to create a function f() that defines that ordering for the sorting procedure. That f() will take the letters or customers or whatever and will return an integer for each one that the computer can actually sort on.
At least, that's how the problem is described. I personally would have designed a predicate that accepted two items, x and y and returned a boolean if x < y. But whichever is fine.
The code wants you to rewrite the insertion sort algorithm, but using a function as a parameter - thus a higher order function.
I would like to point out that this code, typo included, seems to stem from a piece of work currently due at a certain university - I found this page while searching for "insertion sort algortihm", as I copy pasted the term out of the document as well, typo included.
Seeking code from the internet is a risky business. Might I recommend the insertion sort algorithm wikipedia entry, or the Haskell code provided in your lecture slides (you are looking for the 'insertion sort algorithm' and for 'higher-order functions), as opposed to the several queries you have placed on Stack Overflow?

Why do different operators have different associativity?

I've got to the section on operators in The Ruby Programming Language, and it's made me think about operator associativity. This isn't a Ruby question by the way - it applies to all languages.
I know that operators have to associate one way or the other, and I can see why in some cases one way would be preferable to the other, but I'm struggling to see the bigger picture. Are there some criteria that language designers use to decide what should be left-to-right and what should be right-to-left? Are there some cases where it "just makes sense" for it to be one way over the others, and other cases where it's just an arbitrary decision? Or is there some grand design behind all of this?
Typically it's so the syntax is "natural":
Consider x - y + z. You want that to be left-to-right, so that you get (x - y) + z rather than x - (y + z).
Consider a = b = c. You want that to be right-to-left, so that you get a = (b = c), rather than (a = b) = c.
I can't think of an example of where the choice appears to have been made "arbitrarily".
Disclaimer: I don't know Ruby, so my examples above are based on C syntax. But I'm sure the same principles apply in Ruby.
Imagine to write everything with brackets for a century or two.
You will have the experience about which operator will most likely bind its values together first, and which operator last.
If you can define the associativity of those operators, then you want to define it in a way to minimize the brackets while writing the formulas in easy-to-read terms. I.e. (*) before (+), and (-) should be left-associative.
By the way, Left/Right-Associative means the same as Left/Right-Recursive. The word associative is the mathematical perspective, recursive the algorihmic. (see "end-recursive", and look at where you write the most brackets.)
Most of operator associativities in comp sci is nicked directly from maths. Specifically symbolic logic and algebra.