参数化类型
定义
与 C# 和 Java 中的泛型一样,参数化类型允许您创建可以容纳其他类型的“容器”。例如,List 表示仅包含字符串的 List,KeyValuePair 表示一对值,其中 int 用作 string 的键。通常,您使用泛型类型来约束 Container 类型可以采用的值的类型,以使其更易于使用。在 Haskell 中,也是如此。
您可以创建的最基本的参数化类型是一个 Box,它充当任何其他类型的容器。
GHCi> n = 6 :: Int GHCi> :t Box n Box n :: Box Int GHCi> word = “box” GHCi> :t Box word Box word :: Box [Char] GHCi> f x = x GHCi> :t Box f Box f :: Box (t -> t)
还可以为您的盒子创建简单的功能,例如包装和展开以将物品放入盒子或将其从盒子中取出。
wrap :: a -> Box a wrap x = Box x unwrap :: Box a -> a unwrap (Box x) = x
最常见的参数化类型是列表。 List 类型很有趣,因为它具有与您见过的大多数其他类型不同的构造函数。如您所知,您使用括号来构造一个列表并将值放入其中
类型的类型
Haskell 类型与函数和数据的另一个共同点是它们也有自己的类型!类型的类型称为其kind。
类型的kind指示该类型采用的参数数量,使用星号 (_) 表示。不带参数的类型具有一种 _,带一个参数的类型具有 _ -> _ 类型,具有两个参数的类型具有 _ -> _ -> * 类型,依此类推。
Kind 的作用
- 描述类型构造器的类别:Kind 表示类型构造器需要多少个类型参数。例如:
Int :: *
表示Int
是一个具体类型,没有参数(即是一个具体的值类型)。Triple :: * -> *
表示Triple
是一个类型构造器,接受一个类型参数并返回一个新类型。[] :: * -> *
表示列表类型构造器接受一个类型参数(如Int
、Char
等),并返回一个列表类型。(,) :: * -> * -> *
表示元组类型构造器接受两个类型参数并返回一个元组类型。Map.Map :: * -> * -> *
表示Map
是一个类型构造器,接受两个类型参数(键和值)并返回一个新的映射类型。
- 类型安全性:通过使用 kind,可以确保在类型系统中使用的类型构造器是正确的。例如,试图将一个类型应用于错误数量的参数将导致编译错误。
Kind 和 *
的关系
*
是一种特殊的 kind,表示一个具体的值类型(例如Int
、Bool
、Char
等)。这些类型在运行时是可以存在的,可以被实例化为具体的值。-> *
表示一个接受一个具体类型并返回一个具体类型的类型构造器。例如,[]
是一个接受类型参数的类型构造器,返回一个列表类型。
GHCi> :kind Int
Int :: *
GHCi> :kind Triple
Triple :: * -> *
GHCi> :kind []
[] :: * -> *
GHCi> :kind (,)
(,) :: * -> * -> *
GHCi> :kind Map.Map
示例解析
Int :: *
:Int
是一个具体类型。Triple :: * -> *
:Triple
是一个接受一个类型参数的类型构造器。[] :: * -> *
:[]
是列表类型构造器,接受一个类型参数并返回列表类型。(,) :: * -> * -> *
:元组类型构造器,接受两个类型参数。Map.Map :: * -> * -> *
:Map
类型构造器,接受键和值的类型并返回映射类型。
data.map
另一个有用的参数化类型是 Haskell 的 Map(不要与 map 函数混淆)。要使用Map,首先必须导入Data.Map。由于 Data.Map 模块与 Prelude 共享一些功能,因此您将进行合格的导入.
import qualified Data.Map as Map
Map 允许您使用键查找值。在许多其他语言中,这种数据类型称为字典。 Map的类型参数是键和值的类型。与列表和元组不同,Map 的实现并不简单。理解这种类型的最好方法是通过一个具体的例子
data Organ = Heart | Brain | Kidney | Spleen deriving (Show, Eq)
organs :: [Organ]
organs = [Heart,Heart,Brain,Spleen,Spleen,Kidney]
ids :: [Int]
ids = [2,7,13,14,21,24]
organPairs :: [(Int,Organ)]
organPairs = zip ids organs
organCatalog :: Map.Map Int Organ
organCatalog = Map.fromList organPairs
GHCi> Map.lookup 7 organCatalog
Just Heart
参数化类型是一种采用一个或多个参数的类型(如大多数 OOP 语言中的泛型)。参数化类型最常见的实例是 List,它可以包含任何类型的元素。参数化类型可以采用任意数量的类型作为参数。参数化类型作为参数的类型数量定义了其类型。
两个类型定义:
fromList :: Ord k => [(k,a)] -> Map k a
Map.lookup :: Ord k => k -> Map.Map k a -> Maybe a