1

I wonder if it is possible to create variables from an iterable of things in Haskell. I found this when I search for it but I couldn't adapt it for my case. Maybe it's not possible or I'm missing something since I'm a beginner. Basically, I'm wondering if something like this is possible in Haskell:

>>> list_of_lists = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> a, b, c = list_of_lists
>>> print(a)
[1, 2, 3]
Asocia
  • 5,935
  • 2
  • 21
  • 46
  • 4
    You can unpack it, for example `let [a, b, c] = [[1,2,3], [4,5,6], [7,8,9]] in a`. It is however nothing "special", like it is in Python, it is simple pattern matching. For most foldables (like `Tree`, `Maybe`, etc.), you can use `toList`. – Willem Van Onsem Jun 02 '20 at 17:30
  • 4
    It's called [pattern matching](https://en.wikibooks.org/wiki/Haskell/Pattern_matching) and alongside lists, it works on many data types. – Redu Jun 02 '20 at 17:33

2 Answers2

7
ghci> list_of_lists = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
ghci> [a,b,c] = list_of_lists
ghci> print a
[1,2,3]
luqui
  • 59,485
  • 12
  • 145
  • 204
2

The answer given by luqui works when the list has exactly three elements. It is, however, partial, which means that it'll fail at run-time for lists of any other size.

A more idiomatic Haskell solution, I think, would be a function like this:

listToTriple :: [a] -> Maybe (a, a, a)
listToTriple [a, b, c] = Just (a, b, c)
listToTriple _ = Nothing

You can safely call it with lists of any length:

*Q62157846> listToTriple [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Just ([1,2,3],[4,5,6],[7,8,9])
*Q62157846> listToTriple [[1, 2, 3], [4, 5, 6]]
Nothing
*Q62157846> listToTriple [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
Nothing

If, in the first case, you only want the first of those three lists, you can pattern-match on the triple:

*Q62157846> fmap (\(a, _, _) -> a) $ listToTriple [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Just [1,2,3]
Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • I actually am sure that my list will have exactly 3 elements so it will not create any problem for this case. But I was also thinking that how would I proceed if the list has unknown size. So this definitely helps, thanks for the clarification! – Asocia Jun 02 '20 at 19:08
  • 5
    @Asocia If you're sure that you have exactly three elements, a triple `(,,)` would be a better type to use than a list. – Mark Seemann Jun 02 '20 at 19:11
  • I'd strongly hesitate to recommend tuples here. Because they're in general heterogeneous, they offer much less convenient features than lists when used as homogeneous containers. In fact I tend to say tuples should _only_ be used when grouping together two elements of unknown, possibly different type. Honestly, a list is probably the most sensible solution. Sure, some type guarantee would be nice, but Haskell isn't a total language and often it's just not feasible. (Though it _should_ actually be doable nicely if the `IsString` class had an extra `Nat` parameter.) – leftaroundabout Jun 03 '20 at 13:19
  • @leftaroundabout One could define `data Triple a = Triple a a a`, then... – Mark Seemann Jun 03 '20 at 13:23
  • 1
    ...or use a library one, such as [`Linear.V3`](https://hackage.haskell.org/package/linear/docs/Linear-V3.html). – leftaroundabout Jun 03 '20 at 13:24
  • @leftaroundabout I didn't know about that library. Thank you :) – Mark Seemann Jun 03 '20 at 13:26
  • Well, I'm not creating my iterable manually. I'm using `groupBy` function, and I know I will have 3 groups at the end. So I just wanted to assign these groups to separate variables :) – Asocia Jun 03 '20 at 15:20