Can this haskell sample be shorter?

haskell

Solution

I would try to keep it dead simple:

data Tuplex a b c d = Tuple1 a | Tuple2 a b | Tuple3 a b c | Tuple4 a b c d

toMaybes (Tuple1 p)       = (Just p, Nothing, Nothing, Nothing)
toMaybes (Tuple2 p q)     = (Just p, Just  q, Nothing, Nothing)
toMaybes (Tuple3 p q r)   = (Just p, Just  q, Just  r, Nothing)
toMaybes (Tuple4 p q r s) = (Just p, Just  q, Just  r, Just  s)

tuple1 t = p where (p,_,_,_) = toMaybes t 
tuple2 t = q where (_,q,_,_) = toMaybes t 
tuple3 t = r where (_,_,r,_) = toMaybes t 
tuple4 t = s where (_,_,_,s) = toMaybes t

Problem

This is my solution to exercise from YAHT: Exercise 4.6 Write a datatype Tuple which can hold one, two, three or four elements, depending on the constructor (that is, there should be four constructors, one for each number of arguments). Also provide functions tuple1 through tuple4 which take a tuple and return Just the value in that position, or Nothing if the number is in valid (i.e., you ask for the tuple4 on a tuple holding only two elements). When I wrote a first line I was excited about simplicity comparing to C# ``` data Tuplex a b c d = Tuple1 a | Tuple2 a b | Tuple3 a b c | Tuple4 a b c d -- 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 access any field without problem, but here I should write an 'accessor functions', right? And amount of code here makes me sad. Can I have shorter code here? ``` tuple1 ∷ Tuplex a b c d → Maybe a tuple2 ∷ Tuplex a b c d → Maybe b tuple3 ∷ Tuplex a b c d → Maybe c tuple4 ∷ Tuplex a b c d → Maybe d tuple1 (Tuple1 a) = Just a tuple1 (Tuple2 a b) = Just a tuple1 (Tuple3 a b c) = Just a tuple1 (Tuple4 a b c d) = 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' ```

Original source