Reputation: 247
I am new to Haskell and trying to see how it works. I want to define a function in Haskell that could take a list of tuples, those tuples could be pair, 3-tuple, 4-tuple, 5-tuple and etc
functionY [(a,b)]
Then I cannot call it with 3-tuple element like [(1,2,3),(2,3,4)]
functionY [(1,2,3),(2,3,4)] // will complain
How would I fix this? thanks
Upvotes: 1
Views: 208
Reputation: 47382
Here is one approach, which is suitable if you don't mind writing a bit of boilerplate code. Conceptually, all that matters about an n-tuple is that it is a data structure with n slots that you can get access to. Every n-tuple for n >= m should have a method called get-m that gets whatever data is in the m'th slot. We can abstract that into a typeclass by using functional dependencies
{-# LANGUAGE FunctionalDependencies, FlexibleInstances #-}
class HasFirst a b | a -> b where
get1 :: a -> b
class HasSecond a b | a -> b where
get2 :: a -> b
Those type classes describe data that have a "first" and a "second" slot. We can write instances for 2-tuples and 3-tuples as follows
instance HasFirst (a,b) a where
get1 (a,_) = a
instance HasSecond (a,b) b where
get2 (_,b) = b
instance HasFirst (a,b,c) a where
get1 (a,_,_) = a
instance HasSecond (a,b,c) b where
get2 (_,b,_) = b
Now you can write a function that is generic over all data structures that have a "second" slot, for example
getSeconds :: HasSecond a b => [a] -> [b]
getSeconds = map get2
And use it as follows
>>> getSeconds [(1,2), (4,5)]
[2,5]
>>> getSeconds [(1,2,3), (4,5,6)]
[2,5]
Upvotes: 4