繁体   English   中英

构造函数作为Haskell中的数据类型

[英]Constructors as datatypes in Haskell

目前,我有以下数据类型:

data NumberColumn = NumberColumn String [Double]
data StringColumn = StringColumn String [String]
data UnknownColumn = UnknownColumn String [String]

所有这些数据类型(也有其他数据类型,它们只是域示例)对csv文件列建模。 它们可以代表纯数字,名称,货币,简单文本等。

我想要实现的是这样的:

data Column = NumberColumn String [Double] | StringColumn String [String] | UnknownColumn String [String]

也就是说,我想将它们放在单个数据类型中,以便可以映射,过滤和创建新项目,如下所示:

sumColumn :: NumberColumn -> NumberColumn -> NumberColumn
sumColumn...

问题在于NumberColumn不是数据类型而是构造函数,所以我能想到的最好的办法是接受并返回Column类型:

sumColumn :: Column -> Column -> Column
sumColumn (NumberColumn...) (NumberColumn...)...

这行得通,但是该函数只能使用NumberColumns的明确性丢失了,我非常想保留它。

能做到吗?

似乎您想将单个类型构造函数Column定义为

data Column a = Column String [a]

然后

sumColumn :: Column Double -> Column Double -> Column Double
sumColumn (Column name values) = ...

要将StringColumnUnknownColumn与原始字符串区分开,请使用Unknown的新类型将其与“普通”字符串区分开。

newtype Unknown = Unknown String

type UnknownColumn = Column Unknown  -- for example

您可以这样将NumberColumn构造函数的数据分解为新的数据类型:

data Column
    = NumberColumn  NumCol
    | StringColumn  String [String]
    | UnknownColumn String [String]

data NumCol = NumCol String [Double]

sumColumn然后在定义NumCol唯一的,而不是Column S或NumberColumn S:

sumColumn :: NumCol -> NumCol -> NumCol
sumColumn (NumCol s1 d1) (NumCol s2 d2) = ...

编辑:

如果你想NumCol s到行为像NumberColumn S,你可以使用一个类型的类:

class Columnlike a where
    toColumn :: a -> Column

instance Columnlike Column where
    toColumn = id

instance Columnlike NumCol where
    toColumn = NumberColumn

有了这个类型类,您在Column的函数现在可以在某些Columnlike a ,并且可以互换使用NumColColumn 例如:

colFunction :: Column -> Column
colFunction = ...

变成

colFunction :: Columnlike a => a -> a
colFunction = ...

然后你可以使用colFunctionNumCol S和NumberColumn小号的一致好评。

除了chepner的

data Column a = Column String [a]

您可以将sumColumn定义为

sumColumn :: Num a => Column a -> Column a -> Column a
sumColumn (Column name1 ms) (Column name2 ns) =
  Column (name1 ++ "+" ++ name2) (zipWith (+) ms ns)

您还可以使用GADT来确保仅以数字形式使用包含数字的列:

{-# LANGUAGE GADTs #-}

data Column a where
  NumColumn :: Num a => String -> [a] -> Column a
  StrColumn :: String -> [String] -> Column String

但是您仍然必须约束在Num a => Column a s上运行的每个函数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM