gpt4 book ai didi

Why typescript cannot refer the type in my example correctly?(为什么TypeScrip不能正确引用我示例中的类型?)

转载 作者:bug小助手 更新时间:2023-10-26 20:32:43 29 4
gpt4 key购买 nike



Considering the code for Option ADT as below (pretty similar to fp-ts Option):

选项adt的代码如下(与fp-ts选项非常相似):


export type Option<A> = Some<A> | None

export interface Some<A> {
_tag: 'Some'
value: A
}

export interface None {
_tag: 'None'
}

export const some = <A>(x: A): Option<A> =>
({ _tag: 'Some', value: x })

export const none: Option<never> =
{ _tag: 'None' }

export const isNone = <A>(x: Option<A>): x is None =>
x._tag === 'None'

type Match = <A, B>(onNone: () => B, onSome: (a: A) => B)
=> (x: Option<A>) => B

const match: Match = (onNone, onSome) => x =>
isNone(x) ? onNone() : onSome(x.value)

I'm trying to write the Option map Functor mapOption, but it cannot refer the types correctly. You can also see the error in this typescript playground.

我正在尝试编写选项映射函数mapOption,但它无法正确引用类型。你也可以在这个打字操场上看到错误。


type MapOption = <A, B>(f: (x: A) => B) => (fa: Option<A>) => Option<B>
const mapOption: MapOption = f => fa => match(
() => none,
(value) => f(value))(fa)

For some reason it is inferring the types incorrectly. How can I fix the typing error?

出于某种原因,它错误地推断了类型。我怎样才能改正打字错误呢?


更多回答

① I think you must mean "infer" instead or "refer". Could you edit to fix that? ② Could you edit demonstrate how "inlining the types inside mapOption" would fix the typing error and then we look at helping you avoid it? I tried to do it but I'm having trouble, and when I try to fix it I end up changing your implementation to const mapOption: MapOption = f => match(() => none, value => some(f(value))), which type-checks fine but maybe I'm missing the point? Help!

①我想你的意思一定是“推断”或“参考”。你能修改一下吗?②你能编辑演示如何“内联mapOption内的类型”将修复键入错误,然后我们看看帮助你避免它?我试着这样做,但我遇到了麻烦,当我试图修复它时,我最终将您的实现更改为const mapOption:MapOption = f => match(()=> none,value => some(f(value),类型检查很好,但也许我错过了重点?救命啊!

Thank you @jcalz, I fixed the question and you are correct! my implementation was incorrect. I needed to wrap my value in some to make it an Option. The interesting part is, when you make the implementation of a the function point-free, the type error goes away, and that's completely enough. But can you help me understand why literally calling the match with fa, makes value to be inferred to unknown?

谢谢@jcalz,我解决了这个问题,你是正确的!我的实现是不正确的。我需要把我的价值包装在一些东西里,使之成为一个期权。有趣的是,当你实现一个函数时,类型错误就消失了,这就足够了。但是你能帮助我理解为什么字面上用fa调用match,会使value被推断为unknown吗?

I'm confused by the question: you're wondering why an incorrect implementation would result in inference failure? (Generally things fall back to unknown if they can't be inferred). I'm not sure what the alternative could be, but maybe I'm not getting it. Could you edit to present a minimal reproducible example something where the only problem present is the inference issue? Or leave it as-is and I'll write up the answer saying the reason it fails is that the implementation is incorrect. Let me know how to proceed.

我被这个问题搞糊涂了:您想知道为什么不正确的实现会导致推理失败?(通常情况下,如果无法推断,事情就会退回到未知状态)。我不确定另一种选择是什么,但可能我不明白。你能编辑出一个最小的可重现的例子吗?唯一存在的问题就是推理问题。或者让它保持原样,我会写出答案,说它失败的原因是实现不正确。请让我知道如何继续。

When I was writing the question, I wasn't realize my mistake. My implementation was incorrect, so obviously it was giving me typing error. you caught it, Thank you @jcalz. If you write an answer I will mark it as the solution, so you get the credit and points. Thank you again.

当我写问题的时候,我没有意识到我的错误。我的实现是不正确的,所以很明显它给了我输入错误。你抓住了,谢谢你@jcalz。如果你写一个答案,我会把它标记为解决方案,所以你得到学分和积分。再次感谢你。

优秀答案推荐

One problem with your code was that it was not correct, so really there's no hope at all of the compiler inferring the types properly. The proper implementation looks like this:

您的代码的一个问题是它不正确,所以实际上编译器完全没有希望正确地推断类型。正确的实现如下所示:


const mapOption: MapOption = f => fa => (
match(
() => none,
value => some(f(value)) // error!
// -----------> ~~~~~
// Argument of type 'unknown' is not assignable to parameter of type 'A'.
)
)(fa);

But, as you can see, the inference issue remains. The compiler fails to infer the type of value from context, and thus it falls back to the unknown type.

但是,正如你所看到的,推理问题仍然存在。编译器无法从上下文中推断出值的类型,因此它会退回到未知类型。


This sort of thing is ultimately a design limitation of TypeScript. The language can't always infer generic type arguments and simultaneously infer types from context. The currently open issue about the general problem is microsoft/TypeScript#47599.

这类事情归根结底是打印脚本的设计局限性。该语言并不总是能在推断泛型类型参数的同时从上下文中推断类型。目前关于该一般问题的未决问题是MICROSOFT/TypeScrip#47599。


While there have been improvements here over the years, it's probably always going to be there in some form. TypeScript does not use a full unificiation algorithm for type inference, as in some other functional programming languages, and as requested in microsoft/TypeScript#30134.

虽然多年来这里已经有了改进,但它可能永远会以某种形式存在。与其他函数式编程语言和微软/TypeScrip#30134中的要求不同,TypeScrip不使用完整的统一算法进行类型推理。


And it probably never will use such an algorithm, since (according to this comment on microsoft/TypeScript#17520), the current inference algorithm "has the distinct advantage of being able to make partial inferences in incomplete code which is hugely beneficial to statement completion in IDEs."

而且它可能永远不会使用这样的算法,因为(根据微软/TypeScrip#17520上的这条评论),当前的推理算法“具有独特的优势,能够在不完整的代码中进行部分推断,这对IDE中的语句完成非常有益。”




We have to work around this if you want your code to compile. One way is to do the thing you don't want to do: "inline" the types. Maybe like this:

如果您想要编译代码,我们必须解决这个问题。一种方法是做你不想做的事情:“内联”类型。也许是这样的:


const mapOption: MapOption = f => fa => (
match(
() => none,
(value: Parameters<typeof f>[0]) => some(f(value))
)
)(fa);

Here I'm using the Parameters utility type to get a handle on the anonymous generic type parameter corresponding to A. Otherwise you'd have to do it very explicitly and actually declare the type parameters:

在这里,我使用参数实用程序类型来获取对应于A的匿名泛型类型参数的句柄。否则,您必须非常显式地执行此操作,并实际声明类型参数:


const mapOption3: MapOption = <A, B>(f: (x: A) => B) => (fa: Option<A>) => (
match(
() => none,
(value: A) => some(f(value))
)
)(fa);

Another workaround is to make use of some point-free style to eliminate fa and thus make type inference easier by shortening the "distance" between the expected return type and the required input type:

另一种解决方法是使用一些无点样式来消除fa,从而通过缩短预期返回类型和所需输入类型之间的“距离”来更容易地进行类型推断:


const mapOption: MapOption = f => match(
() => none,
value => some(f(value))
);

This way is probably ideal for the particular code example, but you might need to resort to one of the earlier approaches in general. Without full unification, you'll have to specify types in some places where they might have otherwise been inferred.

对于特定的代码示例,这种方法可能是理想的,但通常您可能需要求助于较早的方法之一。如果没有完全统一,您将不得不在某些地方指定类型,否则可能会推断出这些类型。


Playground link to code

游乐场链接到代码


更多回答

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