3

我从事函数式编程已经有一段时间了,但我对幺半群和其他纯抽象还是陌生的。我想知道是否有一种方法可以通过使用concat为 monoid 定义的函数来生成值列表?

例如,以 0 作为单位(单位)和+作为concat,整数成为一个幺半群。如果我想要一个有序整数序列,我可以应用+到我需要的第一个整数和1(这将是这里的一个步骤),然后对结果重复该过程,依此类推。这将生成一个类似的列表[1, 2, 3, 4, 5, ...]

类似地,对于更复杂的 monoid,如果定义了 Event monoid,具有特殊值作为标识,并且concat它需要两个事件并产生一个保持相同间隔的新事件,我可以有一个序列[ Event(Today, 12:00), Event(Today, 12:10), Event(Today, 12:20) ](所以间隔是 10 分钟)。

我的问题是:是否有任何标准模式/抽象/通过应用于concat上一个项目和步骤/间隔来生成此类序列的方式?我正在使用fp-ts图书馆,我试图找到可以做到的东西,但没有任何运气。我可以unfold用来生成一个值数组,但是这个函数只将一个值传递给回调,而我需要两个值concat才能工作

4

1 回答 1

0

此函数仅将一个值传递给回调,而我需要两个值concat才能工作

这是模块中的unfold类型Array

export declare const unfold: <A, B>(b: B, f: (b: B) => O.Option<readonly [A, B]>) => A[]

尽管看起来B只能是“一个值”,但您始终可以返回一个元组,以便您可以访问f.

fp-ts 目前不支持无限列表,所以这里有一个使用length参数来限制结果大小的例子:

import * as A from 'fp-ts/Array'
import {none, some} from 'fp-ts/Option'
import type {Monoid} from 'fp-ts/Monoid'

const concatList = <M>(M: Monoid<M>) => (step: M) => (length: number): M[] =>
  A.unfold<M, [M, number]>([M.empty, 0], ([prev, currentLength]) => {
    if (currentLength === length) return none
    const next = M.concat(prev, step)
    return some([next, [next, currentLength + 1]])
  })

用法:

import {MonoidSum} from 'fp-ts/number'

concatList(MonoidSum)(1)(5) // [1, 2, 3,  4,  5]
concatList(MonoidSum)(3)(5) // [3, 6, 9, 12, 15]
于 2021-07-06T04:14:03.903 回答