Why use lambda instead of matching pattern?

I am looking at the parser tutorial at haskell https://www.youtube.com/watch?v=9FGThag0Fqs . The lecture begins with the definition of some really basic parsers. They should be used together to create more complex parsers later. One of the main parsers is the element. This is used to extract the character from the string we are processing.

All parsers are of the following type:

type Parser a = String -> [(a, String)] 

The analyzer element is defined as follows:

 item :: Parser Char item = \inp -> case inp of [] -> [] (x:xs) -> [(x,xs)] 

I'm not used to this syntax, so it seems strange to me. I would write this:

 item' :: Parser Char item' [] = [] item' (x:xs) = [(x,xs)] 

Testing in ghci means they are equal:

 *Main> item "" [] *Main> item "abc" [('a',"bc")] *Main> item' "" [] *Main> item' "abc" [('a',"bc")] 

The lecturer makes a short comment that he looks clearer, but I do not agree. So my questions are:

Are they really identical? Why is the lambda version clear?
+5
source share
3 answers

I believe this comes from the usual practice of writing

 f :: Type1 -> ... -> Typen -> Result f x1 ... xn = someResult 

where we have exactly n function arrows in type and exactly n arguments on the left side of the equation. This simplifies the comparison of types and formal parameters.

If Result is a type alias for a function, we can write

 f :: Type1 -> ... -> Typen -> Result f x1 ... xn y = something 

or

 f :: Type1 -> ... -> Typen -> Result f x1 ... xn = \y -> something 

The latter follows the convention above: n arrows, n variables on the left. In addition, on the right side, we have something like Result , which simplifies the definition. The first one is not instead, and you can skip the extra argument when reading code quickly.

In addition, this style simplifies converting Result to newtype instead of a type alias:

 newtype Result = R (... -> ...) f :: Type1 -> ... -> Typen -> Result f x1 ... xn = R $ \y -> something 

The published item :: Parser Char code is an instance of this style when n=0 .

+11
source

Why you should avoid the definitions of equational functions (Roman Cheplyak): http://ro-che.info/articles/2014-05-09-clauses

The main points from the above link:

  • DRY: function and argument names repeated β†’ harder refactoring
  • Clearer shows which arguments the function decides
  • Easy to add pragmas (e.g. for profiling)
  • Syntactically closer to the lower code level

That doesn't explain lambda though ..

+4
source

I think they are absolutely equal. The lambda style definition puts the name item on the anonymous lambda function that makes the template inside. Defining a pattern matching style defines it directly. But in the end, both functions perform pattern matching. I think this is a matter of personal taste.

In addition, the definition of the lambda style can be considered as a pointfree style, that is, a function defined without explicitly writing down its arguments is actually not very simple, since the argument is still written (but elsewhere), but in this case you’re nothing don't get with it.

Here is another possible definition, somewhere between the two:

 item :: Parser Char item inp = case inp of [] -> [] (x:xs) -> [(x, xs)] 

It is essentially identical to the lambda style, but does not make sense.

+3
source

Source: https://habr.com/ru/post/1210256/


All Articles