Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When destructuring tuples in Haskell, where can the elements be used?

I am reading a tutorial that uses the following example (that I'll generalize somewhat):

f :: Foo -> (Int, Foo)
...
fList :: Foo -> [Int]
fList foo = x : fList bar
  where
    (x, bar) = f foo

My question lies in the fact that it seems you can refer to x and bar, by name, outside of the tuple where they are obtained. This would seem to act like destructuring parameter lists in other languages, if my guess is correct. (In other words, I didn't have to do the following:)

fList foo = (fst tuple) : fList (snd tuple)
      where
        tuple = f foo

Am I right about this behavior? I've never seen it mentioned yet in the tutorials/books I've been reading. Can someone point me to more info on the subject?

Edit: Can anything (lists, arrays, etc.) be destructured in a similar way, or can you only do this with tuples?

like image 689
J Cooper Avatar asked Jan 10 '09 23:01

J Cooper


1 Answers

Seeing your edit, I think what your asking about is Pattern matching.

And to answer your question: Yes, anything you can construct, you can also 'deconstruct' using the constructors. For example, you're probably familiar with this form of pattern matching:

head :: [a] -> a
head (x:xs) = x
head []     = error "Can't take head of empty list"

However, there are more places where you can use pattern matching, other valid notations are:

head xs = case xs of
              (y:ys) -> y
              []     -> error "Can't take head of empty list"

head xs = let (y:ys) = xs
          in y

head xs = y
  where
    (y:ys) = xs

Note that the last two examples are a bit different from the first to because they give different error messages when you call them with an empty list.


Although these examples are specific to lists, you can do the same with other data types, like so:

first :: (a, b) -> a
first tuple = x
  where
    (x, y) = tuple

second :: (a, b) -> b
second tuple = let (x, y) = tuple
               in y

fromJust :: Maybe a -> a
fromJust ma = x
  where
    (Just x) = ma

Again, the last function will also crash if you call it with Nothing.

To sum up; if you can create something using constructors (like (:) and [] for lists, or (,) for tuples, or Nothing and Just for Maybe), you can use those same constructors to do pattern matching in a variety of ways.

like image 158
Tom Lokhorst Avatar answered Sep 30 '22 14:09

Tom Lokhorst