Using a class in a data type constructor

I currently have something like this:

data MyData = SomeData | MoreData | EvenMore data DataLists = DataLists [MyData] [MyData] 

This allows me to explicitly do something like this:

 myDataList :: DataLists myDataList = DataLists [SomeData, MoreData] [EvenMore, SomeData] 

But I would like to do something like this instead:

 -- Static Module File: class MyClass b where evaluate :: b -> Int data SomeData = SomeData data MoreData = MoreData data EvenMore = EvenMore instance MyClass SomeData where evaluate _ = 2 instance MyClass MoreData where evaluate _ = 3 instance MyClass EvenMore where evaluate _ = 4 data DataList = DataList [MyClass] [MyClass] -- Obviously this is wrong 

I want this part of my code to remain static. Because later I would like to add some types using this module to put in a list of data. I need this separately, because the common module will be used in two different projects, and I do not want to continue editing it.

 data MyVeryOwnData = MyVeryOwnData --I should be able to make up as many datastructures as I want instance MyClass MyVeryOwnData where evaluate _ = 99 myList :: DataList myList = DataList [MyVeryOwnData, SomeData] [SomeData, EvenMore] 

I understand that I can just put MyVeryOwnData in the module file as follows:

 data MyData = SomeData | MyVeryOwnData ... instance MyClass MyData where evaluate SomeData = 2 evaluate MoreData = 3 ... etc. 

But I do not want to do this, because, as I said, I want to add an arbitrary number of data types.

+4
source share
1 answer

What you are looking for is called Heterogenous lists, and haskell supports them mainly in two ways: Existentials or GADTs . I will show you an example of executable code that solved the existential problem.

 {-# LANGUAGE ExistentialQuantification #-} class Eval b where evaluate :: b -> Int data SomeData = SomeData data MoreData = MoreData data EvenMore = EvenMore instance Eval SomeData where evaluate _ = 2 instance Eval MoreData where evaluate _ = 3 instance Eval EvenMore where evaluate _ = 4 data Evalable = forall a . Eval a => Evalable a instance Eval Evalable where evaluate (Evalable a) = evaluate a pack :: Eval a => a -> Evalable pack = Evalable data DataLists = DataLists [Evalable] [Evalable] getFirst :: DataLists -> [Evalable] getFirst (DataLists xs ys) = xs main = do let dl = DataLists [pack SomeData, pack EvenMore] [pack MoreData] print . map evaluate . getFirst $ dl 

It should be clear that you can add instance Eval MyVeryOwnData to external modules, and you can pack those values ​​so that they become Evalable , and you can put them in your Datalists .

+6
source

All Articles