gpt4 book ai didi

typescript - 函数式 TypeScript 和泛型

转载 作者:搜寻专家 更新时间:2023-10-30 21:09:53 25 4
gpt4 key购买 nike

我已经为代码练习创建了一个功能性的 TypeScript 解决方案,该解决方案基于同一练习的 Haskell 解决方案。练习是取一个非常大的整数,并找出一组长度为 n 的相邻数字的最大乘积。

我编写了一个柯里化(Currying)函数 groups,它接受一个数字数组并返回一个数组数组,每个嵌套数组由许多数字组成。

例如:

groups([1,2,3,4,5,6,7,8,9])(3)

将返回:

[[1,2,3], [4,5,6], [7,8,9]]

groups 函数:

type groups = <A>(xs: A[]) => (n: number) => A[][];
const groups: groups = xs => n => xs.length < n ? [] : [take(n)(xs)].concat(groups(drop(1)(xs))(n));

// groups uses the functions 'take' and 'drop':

type take = <A>(n: number) => (xs: A[]) => A[];
const take: take = n => xs => xs.slice(0, n);

type drop = <A>(n: number) => (xs: A[]) => A[];
const drop: drop = n => xs => xs.slice(n);

但是 groups 给出了错误:

TS2322: Type '{}[][]' is not assignable to type 'A[][]'.

但是,当我添加 as [] 时,错误消失了:

const groups: groups = xs => n => xs.length < n ? [] : [take(n)(xs)].concat(groups(drop(1)(xs))(n)) as [];

我的第一个问题是:这是为什么?

我声明 groups 的返回类型是 A[][] 并且参数 xs 的类型是 A[] 那么为什么要将其解析为 {}[][]?我不完全理解这是如何工作的。

然后,当我在 Webstorm 中使用 Quokka 运行最终解决方案时,我得到了正确的答案,但又出现了另一个错误。

一、最终解决方案:

const largestProduct = (count: number): number[] => {
const num = '73167176531330624919225119674426574742355349194934969835203127745063262395';
const digits = num.split('').map((x: string) => parseInt(x, 10));

return Math.max(...map(product)(groups(digits)(count)));
};

// the functions 'map' and 'product' used:

type map = <A, B>(f: (a: A) => B) => (xs: A[]) => B[];
const map: map = f => xs => xs.map(f);

type product = (xs: number[]) => number;
const product: product = xs => xs.reduce((acc, x) => acc * x, 1);

带有return 语句的行给出了错误:

TS2322: Type 'number' is not assignable to type 'number[]'

map 函数确实返回 number[] 但我在这里使用展开运算符。例如 Math.max(...[1,2,3]) 不会给出此错误。

我在这里做错了什么?

最佳答案

问题是你的 takedrop 函数在外部函数上有类型参数 A,而这个参数的推理站点(以 xs 参数的形式)在内部函数上。 Typescript 无法真正处理这个问题,它希望在检查第一次调用时确定所有类型参数(例如 take(1)),因为它无处推断 A 从它只是将它推断为 {} 导致您的问题。

最简单的解决方案是在内部函数上移动类型参数:

type groups = <A>(xs: A[]) => (n: number) => A[][];
const groups: groups = xs => n => xs.length < n ? [] : [take(n)(xs)].concat(groups(drop(1)(xs))(n));

type take = (n: number) => <A>(xs: A[]) => A[];
const take: take = n => xs => xs.slice(0, n);

type drop = (n: number) => <A>(xs: A[]) => A[];
const drop: drop = n => xs => xs.slice(n);

顺便说一句,我不是 100% 相信你之前定义函数类型的方法。您可以完全注释箭头函数(包括返回类型):

const groups = <A>(xs: A[]) => (n: number) : A[][] => xs.length < n ? [] : [take(n)(xs)].concat(groups(drop(1)(xs))(n)); 

const take = (n: number) => <A>(xs: A[]) : A[]=> xs.slice(0, n);

const drop = (n: number) => <A>(xs: A[]): A[] => xs.slice(n);

尽管在这种情况下,返回类型对于takedrop 不是严格必需的,并且可以根据返回类型推断(对于group 因为函数的递归性质)

const groups = <A>(xs: A[]) => (n: number) : A[][] => xs.length < n ? [] : [take(n)(xs)].concat(groups(drop(1)(xs))(n)); 

const take = (n: number) => <A>(xs: A[]) => xs.slice(0, n);

const drop = (n: number) => <A>(xs: A[]) => xs.slice(n);

我的偏好是不要编写编译器可以识别的类型。那几次我实际上想要符号的完整类型我只需要将鼠标悬停在它上面就可以知道 TS 为省略的类型推断出什么。但正如我所说,这只是一种偏好,你的方式也很好 :)

关于typescript - 函数式 TypeScript 和泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54045888/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com