是否可以使用Haskell中的列表填充记录?

问题描述

如果我有这样的记录:

data EdgeSet = EdgeSet {
    top :: Int,right :: Int,bottom :: Int,left :: Int,} deriving (Show)

是否可以通过匹配类型列表填充属性

我正在追寻一些东西:

...
where
    edgeList = [1,2,3,4]
    edgeSet = EdgeSet {edgeList}

如果没有,关于我如何比现在的我更简洁的任何想法?

EdgeSet {top=edgeList !! 0,left=edgeList !! 1,bottom=edgeList !! 2,right=edgeList !! 3}

解决方法

我想不出什么比

where
    -- given
    edgeList = [1,2,3,4]
    -- split into components and call the constructor
    [x1,x2,x3,x4] = edgeList
    edgeSet = EdgeSet x1 x2 x3 x4

也许在库中有一些泛型帮助程序,但是我不知道有任何此类事情。

请注意,如果edgeList不长四个元素,则以上代码将在运行时使程序崩溃。如果列表来源不受信任,则可能需要验证列表,例如使用case of并更优雅地处理意外长度。

,

如果您确信所使用的列表将始终仅包含4个元素,那么与Haskell一样,模式匹配是最好的,最易读的选项:

edgeSet = let [a,b,c,d] = edgeList in EdgeSet a b c d

,如果您需要重用它,可以轻松地将其提取到函数中。

请注意,正如我所暗示的,如果给出的长度小于4的列表将崩溃,但是您给出的解决方案也将崩溃。 (实际上,您将使用长度为5或更大的列表,而我的列表则不会-但您可以根据需要轻松调整模式以应对这种情况。)

我不知道Haskell为此提供了更好的语法。我建议重新考虑是否根本需要一个列表-将数据直接馈送到EdgeSet构造函数而不是遍历列表可能会更容易并且更惯用。显然,这部分取决于您首先如何获取这些数据。

还请注意,如果确定只有4个元素,则4元组比列表更安全,因为编译器将确保您具有正确的数字。

,

可能不是您要找的东西,但总可以按照以下方式做一些事情:

module EdgeSet where

data EdgeSet = EdgeSet {
  top :: Int,right :: Int,bottom :: Int,left :: Int
} deriving (Show)

class ListToMyClass a where
  fromListToClass :: [Int] -> a

instance ListToMyClass EdgeSet where
  fromListToClass [a,d] = EdgeSet a b c d

您必须知道列表的长度为4。