This is my exercise solution from YAHT:
Exercise 4.6. Write a Tuple data type that can contain one, two, three, or four elements, depending on the constructor (that is, there must be four constructors, one for each number of arguments). In addition, tuple1 functions via tuple4 that take a tuple and return a value at that position or Nothing if the number is in action (i.e. you request tuple4 on a tuple containing only two elements).
When I wrote the first line, I was in awe of simplicity compared to C #
data Tuplex abcd = Tuple1 a | Tuple2 ab | Tuple3 abc | Tuple4 abcd
- class Tuplex <a, b, c, d> {
- Tuplex (a p1) {_p1 = p1; }
- Tuplex (a p1, b p2) {_p1 = p1; _p2 = p2; }
- Tuplex (a p1, b p2, c p3) {_p1 = p1; _p2 = p2; _p3 = p3; }
- Tuplex (a p1, b p2, c p3, d p4) {_p1 = p1; _p2 = p2; _p3 = p3; _p4 = p4; }
- public Nullable <a> _p1;
- public Nullable <b> _p2;
- public Nullable <c> _p3;
- public Nullable <d> _p4;
-}
In C #, I can easily access any field, but here I have to write "access functions", right? And the amount of code here upsets me.
Can I have a shorter code here?
tuple1 β· Tuplex abcd β Maybe a
tuple2 β· Tuplex abcd β Maybe b
tuple3 β· Tuplex abcd β Maybe c
tuple4 β· Tuplex abcd β Maybe d
tuple1 (Tuple1 a) = Just a
tuple1 (Tuple2 ab) = Just a
tuple1 (Tuple3 abc) = Just a
tuple1 (Tuple4 abcd) = Just a
tuple2 (Tuple1 a) = Nothing
tuple2 (Tuple2 a b) = Just b
tuple2 (Tuple3 a b c) = Just b
tuple2 (Tuple4 a b c d) = Just b
tuple3 (Tuple1 a) = Nothing
tuple3 (Tuple2 a b) = Nothing
tuple3 (Tuple3 a b c) = Just c
tuple3 (Tuple4 a b c d) = Just c
tuple4 (Tuple1 a) = Nothing
tuple4 (Tuple2 a b) = Nothing
tuple4 (Tuple3 a b c) = Nothing
tuple4 (Tuple4 a b c d) = Just d
-- unit tests
prop_tx1 = tuple1 (Tuple1 4) β‘ Just 4
prop_tx2 = tuple1 (Tuple2 4 'q') β‘ Just 4
prop_tx3 = tuple2 (Tuple1 4) β‘ (Nothing β· Maybe Char)
prop_tx4 = tuple2 (Tuple2 4 'q') β‘ Just 'q'