目前我有这样的事情:
data MyData = SomeData | MoreData | EvenMore
data DataLists = DataLists [MyData] [MyData]
Run Code Online (Sandbox Code Playgroud)
这让我显然可以这样做:
myDataList :: DataLists
myDataList = DataLists [SomeData, MoreData] [EvenMore, SomeData]
Run Code Online (Sandbox Code Playgroud)
但我想做一些像这样的事情:
-- 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
Run Code Online (Sandbox Code Playgroud)
我希望我的代码中的那部分保持静态.因为稍后我想在某些类型中添加使用该模块放入数据列表.我需要这个单独的,因为整个模块将用于2个不同的项目,我不想继续编辑它.
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]
Run Code Online (Sandbox Code Playgroud)
我意识到我可以简单地将MyVeryOwnData放在模块文件中,如下所示:
data MyData = SomeData | MyVeryOwnData ...
instance MyClass MyData where
evaluate SomeData = 2
evaluate MoreData = 3
... etc.
Run Code Online (Sandbox Code Playgroud)
但我不想这样做,因为正如我之前所说,我想添加任意数量的数据类型.
您正在寻找的是Heterogenous列表,而haskell主要通过两种方式支持它们:Existentials或GADT.我向您展示了一个可运行的代码示例,它解决了存在问题.
{-# 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
Run Code Online (Sandbox Code Playgroud)
应该很清楚,您可以添加instance Eval MyVeryOwnData外部模块,然后您可以将pack这些值变为Evalable,然后您可以将它们放入您的内部Datalists.