Haskell 记录实际上并不比类型系统的其他部分“结构更少”。每种类型要么完全指定,要么“特别模糊”(即用类型类定义)。
要同时允许HRec
和HRec2
to f
,您有几个选择:
代数类型:
在这里,您定义HRec
和HRec2
记录都成为HRec
类型的一部分:
data HRec = HRec { x :: Int, y :: Bool }
| HRec2 { p :: Int, q :: Bool }
foo :: HRec -> Bool
(或者,也许更惯用:)
data HRecType = Type1 | Type2
data HRec = HRec { hRecType :: HRecType, x :: Int, y :: Bool }
类型类
在这里,您定义foo
为能够接受任何类型作为输入,只要已为该类型编写了类型类实例:
data HRec = HRec { x :: Int, y :: Bool }
data HRec2 = HRec2 { p :: Int, q :: Bool }
class Flexible a where
foo :: a -> Bool
instance Flexible HRec where
foo (HRec a _) = a == 5 -- or whatever
instance Flexible HRec2 where
foo (HRec2 a _) = a == 5
使用类型类可以让你比常规的结构类型走得更远——你可以接受嵌入了必要信息的类型,即使这些类型表面上看起来并不相似,例如:
data Foo = Foo { a :: String, b :: Float }
data Bar = Bar { c :: String, d :: Integer }
class Thing a where
doAThing :: a -> Bool
instance Thing Foo where
doAThing (Foo x y) = (x == "hi") && (y == 0)
instance Thing Bar where
doAThing (Bar x y) = (x == "hi") && ((fromInteger y) == 0)
我们可以运行fromInteger
(或任何任意函数)从我们拥有的数据中获取我们需要的数据!