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?
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!
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.
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.
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".
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With