开始使用 fp-ts:Eq
在这个博客系列中,我会经常谈论“类型类”和“实例”,让我们看看它们是什么以及它们是如何编码的fp-ts。
程序员通过指定一组函数或常量名称及其各自的类型来定义类型类,这些类型对于属于该类的每种类型都必须存在。
在fp-ts类型类中,被编码为 TypeScript interface。
类型类Eq旨在包含允许相等的类型,其声明方式如下
interface Eq<A> {
  /** returns `true` if `x` is equal to `y` */
  readonly equals: (x: A, y: A) => boolean
}
该声明可以解读为
如果在某个类型上定义了一个以相应类型命名的函数,则该类型
A属于类型类Eqequal
那么实例呢?
程序员可以通过使用实例声明来使任何类型成为
A给定类型类的成员,该实例声明定义了特定类型的C所有成员的实现。CA
在fp-ts实例中被编码为静态字典。
例如,这是Eq该类型的实例number
const eqNumber: Eq<number> = {
  equals: (x, y) => x === y
}
实例必须满足以下规律:
- 反身性:equals(x, x) === true,对于x所有A
- 对称性:equals(x, y) === equals(y, x)对于所有x,y在A
- 及物性:如果equals(x, y) === true且equals(y, z) === true,则equals(x, z) === true对于所有x,,在yzA
然后,程序员可以elem按以下方式定义一个函数(确定元素是否在数组中)
function elem<A>(E: Eq<A>): (a: A, as: Array<A>) => boolean {
  return (a, as) => as.some(item => E.equals(item, a))
}
elem(eqNumber)(1, [1, 2, 3]) // true
elem(eqNumber)(4, [1, 2, 3]) // false
让我们Eq为更复杂的类型编写一些实例
type Point = {
  x: number
  y: number
}
const eqPoint: Eq<Point> = {
  equals: (p1, p2) => p1.x === p2.x && p1.y === p2.y
}
我们甚至可以尝试equals通过首先检查引用相等性来优化
const eqPoint: Eq<Point> = {
  equals: (p1, p2) => p1 === p2 || (p1.x === p2.x && p1.y === p2.y)
}
不过,这基本上只是样板代码。好消息是,我们可以Eq为结构体构建一个实例,就像为每个字段Point提供一个实例一样。Eq
事实上,该fp-ts/Eq模块导出了一个getStructEq 组合器:
import { getStructEq } from 'fp-ts/Eq'
const eqPoint: Eq<Point> = getStructEq({
  x: eqNumber,
  y: eqNumber
})
我们可以继续使用getStructEq刚刚定义的实例
type Vector = {
  from: Point
  to: Point
}
const eqVector: Eq<Vector> = getStructEq({
  from: eqPoint,
  to: eqPoint
})
getStructEq不是提供的唯一组合器fp-ts,这里有一个允许Eq为数组派生实例的组合器
import { getEq } from 'fp-ts/Array'
const eqArrayOfPoints: Eq<Array<Point>> = getEq(eqPoint)
最后,构建Eq实例的另一种有用方法是组合器:给定forcontramap的实例和从到 的函数,我们可以派生出for的实例EqABAEqB
import { contramap } from 'fp-ts/Eq'
type User = {
  userId: number
  name: string
}
/** two users are equal if their `userId` field is equal */
const eqUser = contramap((user: User) => user.userId)(eqNumber)
eqUser.equals({ userId: 1, name: 'Giulio' }, { userId: 1, name: 'Giulio Canti' }) // true
eqUser.equals({ userId: 1, name: 'Giulio' }, { userId: 2, name: 'Giulio' }) // false
下一篇订单
文章来源:https://dev.to/gcanti/getting-started-with-fp-ts-setoid-39f3 后端开发教程 - Java、Spring Boot 实战 - msg200.com
            后端开发教程 - Java、Spring Boot 实战 - msg200.com