haskell类型
Haskell 类型
在Int等默认内置类型外,haskell支持创建自定义的类型系统.这里说的类型更像c中的struct和class,可以有多个类型和不同取值的组合.对于稍微复杂的系统,使用自定义和库里的类型是不可避免的
数据类型定义
基础数据类型
1 | data Bool = False | True |
data
关键字用于定义新的数据类型,Bool
是类型名,False
和 True
是值构造器,分别表示布尔值的两种可能性.|
表示或.
注意:类型名和值构造器的首字母必须大写.
- 数据类型:Haskell 中的数据类型定义类似于枚举,表示一个类型的所有可能值.
- 值构造器:它们是构造类型值的方式,可以理解为是某种“标签”,标明当前值属于哪个分支.
eg:
1 | data Shape = Circle Float Float Float | Rectangle Float Float Float Float |
Circle
和Rectangle
是值构造器,同时也是函数,接受Float
类型参数.类型
Shape
表示几何图形.Circle Float Float Float
:第一个和第二个Float
表示圆心的坐标,第三个Float
表示半径.Rectangle Float Float Float Float
:四个Float
分别表示矩形对角线两点的坐标.
我们可以基于 Shape
定义函数,例如计算面积:
1 | surface :: Shape -> Float |
自动派生类型
可以使用 deriving
自动生成某些类型类的实例:
1 | data Shape = Circle Float Float Float deriving (Show) |
deriving
:Haskell 提供了自动派生功能,能够为常见的类型类生成默认实现.这允许Shape
类型的值可以直接使用print的方法输出,就行Int和Char一样.可以理解为oop中的子类
嵌套数据类型
1 | data Point = Point Float Float deriving (Show) |
通过组合类型 Point
,Shape
描述了更复杂的几何形状.
- 组合数据类型:
Point
是一个更抽象的数据类型,用于表示二维空间中的点.Shape
使用Point
类型参数化了几何形状,提升了表达能力.
类型参数与泛型
1 | data Maybe a = Nothing | Just a |
Maybe
是带类型参数 a
的类型构造器,可表示“可能存在”或“不存在”的值,例如 Maybe Int
或 Maybe String
.
- 类型参数:
a
是一个占位符,表示可以接受任何类型. - 用途:
Maybe
类型常用于处理可能失败的计算,类似于其他语言中的Optional
或Nullable
.
泛型向量定义
1 | data Vector a = Vector a a a deriving (Show) |
此定义适用于不同类型的三维向量.
- 泛型参数
a
:表示向量的分量类型,例如可以是Int
或Float
. vplus
函数:定义了两个向量的逐元素加法.
类型类与实例
类型类类似于接口,定义了一组通用行为.例如,Eq
类型类定义了相等性:
1 | class Eq a where |
- 类型类:类似于接口,描述了一组类型支持的操作.
- 默认实现:
Eq
中提供了==
和/=
的默认实现,减少了实例化类型类的重复工作.
为数据类型实现类型类
以交通信号灯为例:
1 | data TrafficLight = Red | Yellow | Green |
instance
:用于为具体的数据类型定义类型类的实现.- 模式匹配:通过具体值的匹配,实现
TrafficLight
的Eq
实例.
常见类型类
Eq
: 支持相等性判断.Ord
: 支持排序.Show
: 支持打印.Read
: 支持字符串解析.Enum
: 支持枚举.Bounded
: 支持上下界.
eg:
1 | data Day = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday |
- 多重派生:
Day
同时派生了多个类型类实例,使其支持相等性比较、排序、打印等操作. - 范围操作:
Bounded
和Enum
的实例使得可以生成枚举范围.
Functor 与递归数据结构
Functor 类型类
Functor
提供了一种将函数应用于容器内值的方式:
1 | class Functor f where |
f
是类型构造器:它接受一个类型参数,例如Maybe
或列表.fmap
:表示将函数应用到容器(如Maybe
或树)中的每个元素.
以 Maybe
为例:
1 | instance Functor Maybe where |
Maybe
的 Functor 实例:定义了如何将函数映射到Maybe
类型的值上.- 用途:允许对容器中的值进行函数操作,而不需要显式解包.
递归数据结构:树
1 | data Tree a = EmptyTree | Node a (Tree a) (Tree a) deriving (Show) |
通过递归方式定义操作:
1 | treeInsert :: (Ord a) => a -> Tree a -> Tree a |
- 递归定义:通过递归调用
treeInsert
,构造或更新树结构. - 平衡性:尽管此处未实现平衡逻辑,但该方法可用于构建基本的二叉搜索树.更复杂的平衡树在haskell中的实现机制需要多加考虑,因为haskell中对于已有数据的修改本质都是创建新副本,使得整个修改过程构成一个巨大的可持久化结构,关于空间使用还需注意