[英]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) = ...
要将StringColumn
和UnknownColumn
与原始字符串区分开,请使用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
,并且可以互换使用NumCol
和Column
。 例如:
colFunction :: Column -> Column
colFunction = ...
变成
colFunction :: Columnlike a => a -> a
colFunction = ...
然后你可以使用colFunction
上NumCol
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.