将类型字段存储在列表中

时间:2018-07-03 14:26:53

标签: haskell algebraic-data-types

你好,我面临以下问题。我有一个具有多个字段的数据类型。我需要枚举它们并将它们存储在一个集合中以进行进一步的映射。

data Worker=Worker{
        age::Int,
        name::String,
        title::Title,
        income::Int
    }


    data Title=Manager | Dev | Tester deriving (Show)



    instance Show Worker where 
        show w=let !names=["age","name", "title","income"] 
                   !props= [age,name,title,income]  in   -- Do i need to define another new type to be able to flat them down to a list?
            "{"++intercalate "," (zipWith (\x y-> x++":"++ y w) names props)++"}"

在我们的例子中,我可以在哪里存储所有属性(方法),以便能够进一步将它们用作高阶函数中类型为Worker的给定变量的参数。

1 个答案:

答案 0 :(得分:1)

您可以大致上找到想要的东西,但这不会很漂亮。

我们可以使用RecordWildCards来将所有访问器名称都视为作用域,就好像它们是普通变量一样,但这仍然引入了一个新问题。

-- Not runnable Haskell code
foo Worker {..} = let names = ["age", "name", "title", "income"]
                      props = [age, name, title, income]
                  in ...

我们正在Worker {..}上进行模式匹配,这将大量访问器名称引入本地范围。但是,props试图成为异构列表,Haskell不允许这样做。它包含两个整数,一个字符串和一个标题,而Haskell列表仅应包含一种类型。

由于要显示每个字段,因此必须手动将show应用于每个元素。就像我说的那样,这将有点难看。

foo Worker {..} = let names = ["age", "name", "title", "income"]
                      props = [show age, show name, show title, show income]
                  in ...

貌似我们可以map show [age, name, title, income],但我们做不到。该列表仍然无效,并且我们在此处应用了三个不同的show函数(它们恰好共享一个名称),因此我们无法有意义地映射 same { {1}}在每个元素上。

但是,正如评论所说,您最好的选择是熟悉一个合适的JSON库,而Aeson无疑是Haskell中此类事情的最佳选择。