Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

explain this haskell funtion "list of tuples to list"

Tags:

haskell

I'm a beginner and basically I need an explanation of this

He answer with this code:

tupleToList :: [(a,a)] -> [a]
tupleToList ((a,b):xs) = a : b : tupleToList xs
tupleToList _          = []

But I don't underdand why he don't use:

tupleToList [] = []
tupleToList ((a,b):xs) = a : b : tupleToList xs

Like I usually see in the first exercises of the guides. I know that '_' is whatever, but, isn't better to use '[]' that mean, when the list is empty?

like image 319
Muribury Lex Avatar asked May 21 '18 09:05

Muribury Lex


People also ask

What is list in Haskell?

In Haskell, lists are a homogenous data structure. It stores several elements of the same type. That means that we can have a list of integers or a list of characters but we can't have a list that has a few integers and then a few characters. And now, a list!

What are tuples in Haskell?

A tuple is a fixed-length coupling of values, written in parentheses with the values separated by commas. One way to use this is to pass all parameters into a function as one value, rather than the curried functions we've seen so far.

How do you know if a list has equal Haskell?

If your lists have always same size then just A == B . Also if your lists don't have the same size, just as == bs tells you if they are equal. @Ingo @mort's "working" solution treats, for example, [1,2,3] and [1,2,3,4] as equal, there (==) would not. I didn't mention list length because it's easy to check.


2 Answers

Like I usually see in the first exercises of the guides. I know that _ is whatever, but, isn't better to use [] that mean, when the list is empty?

Semantically the two are the same since a 2-tuple has only one constructor (a,b), and a list has two constructors [] and (h:t).

Since the only pattern left that is not matched by the first clause is the empty list, the wildcard _ is equivalent to [].

Since [] and ((a,b):xs) are disjunctive patterns (i.e. there are no values that can match both patterns), the order of the two patterns is of no importance, when [] is used explicitly. We can write it in any order we like, then.

Some Haskell programmers prefer to use explicit patterns (so with [] instead of _), since that means that we know which values we actually handle with that clause. If later the Haskell community would decide to introduce an additional list constructor (yes, for lists that is very unlikely, but for other data types this might be more reasonable), the Haskell compiler can (with -Wincomplete-patterns) give warnings that some patterns are not covered. A wildcard of course covers all patterns, but perhaps the expression at the right is not the one we intended for the additional constructor.

Therefore I would advice to use a wildcard only in case you want to match multiple patterns by the same clause. In case it is clear what the other pattern is, it is better to be explicit. Like the Zen of Python says (yes, it is Python, but most concepts are to some extent universal): "explicit is better than implicit".

like image 58
Willem Van Onsem Avatar answered Sep 29 '22 06:09

Willem Van Onsem


There is no difference: their semantics is exactly the same.

tupleToList [] = []
tupleToList ((a,b):xs) = a : b : tupleToList xs

is equivalent to

tupleToList ((a,b):xs) = a : b : tupleToList xs
tupleToList [] = []

which is equivalent to

tupleToList ((a,b):xs) = a : b : tupleToList xs
tupleToList _ = []

Usually, the wildcard _ is used when we need to pattern match multiple cases. E.g.

myAnd :: Bool -> Bool -> Bool
myAnd True  y = y
myAnd False _ = False

Above, we could enumerate the False False and False True cases individually, and use three equations, but using a wildcard is more convenient (and makes our function slightly lazier, e.g. myAnd False undefined evaluates to False).

Concluding, it's mostly a matter of style. Usually, when the wildcard _ can only stand for one case, it is better to spell it out, to be explicit about it. In this way, the code is often more readable. E.g.

not :: Bool -> Bool
not False = True
not _     = False

is equivalent but worse than

not :: Bool -> Bool
not False = True
not True  = False

The same holds for case expression, of course.

case x of
  Just y  -> 1 + y
  Nothing -> 0

is arguably more readable than

case x of
  Just y -> 1 + y
  _      -> 0
like image 42
chi Avatar answered Sep 29 '22 07:09

chi