在F#中的序列表达式中输入推理

编程入门 行业动态 更新时间:2024-10-23 11:28:47
本文介绍了在F#中的序列表达式中输入推理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我认为我不太了解F#如何在序列表达式中推断类型,以及即使直接从seq指定元素的类型,为什么类型不能正确识别。

在下面的F#代码中,我们有一个基类A和两个派生类B和C:

type A (x)= 成员aX = x 类型B(x)= 继承A(x) 类型C(x)= 继承A(x)

如果我试图以简单的顺序屈服它们的实例表达式,我得到两个错误:

//不起作用,但它是有道理的。 let testSeq = seq { yield A(0) yield B(1)//错误,预期类型:A yield C(2)//错误,预期类型:A }

这可能是有道理的,因为它可能不那么微不足道常见类型(接口,我认为可以使这个工作更加困难)。但是,这些错误可以通过安全的转换来解决:

//正常工作:) let testSeqWithCast = seq {收益率A(0)收益率B(1):> A 收益C(2):> A }

如果我不想使用强制转换?我尝试直接从seq中指定序列类型,但似乎并不奏效:

//应该可以工作,我想... let testGenSeq = seq< A> { yield A(0) yield B(1)//错误,预期类型:A yield C(2)}

所以,我的问题是:有没有办法避免强制转换?如果没有,是否有一个原因,甚至指定类型不会使代码工作?

我试着通过以下链接挖掘:

msdn.microsoft/zh-CN/library/dd233209 .aspx http:// lorgonblog .wordpress / 2009/10/25 / overview-of-type-in​​ference-in-f /

但我没有发现任何用处......

预先感谢您提供的任何答案:

解决方案

为了理解混淆的原因,你不应该再去任何地方,比第一条语句您提到的链接:

序列是一系列逻辑元素全部一种类型。

您可以返回一系列仅一个,相同类型,如 seq 或 SEQ<物镜> 。 OOP的事实是,类型 B 和 C 是从 A 不相关。以下可能会有所帮助:您的所有实例也都从 obj 继承,但为了使它们成为 seq< obj> 你应该明确施放:

//正常工作 let testSeq = seq< obj> {产量A(0):> obj 收益率B(1):> obj 收益率C(2):> obj }

或者只是框他们就像下面:

//可以正常工作 let testSeq = seq { yield box( A(0))收益框(B(1))收益框(C(2))}

编辑:为了理解F#中显式转换的原因,以下(简单化)考虑可能会有所帮助。类型推断不会猜测;除非它可以确定性地派生 seq 类型,或者明确声明它,否则会抱怨。

如果你只是做

let testSeq = seq { yield A(0) yield B(1)产量C(2)}

编译器带有不确定性 - testSeq 可以是 seq 或 seq ,所以它抱怨。当你做

let testSeq = seq { yield A(0) yield upcast B(1 )产生upcast C(2)}

它推断 testSeq 作为 seq ,并将B和C上传到 A 没有抱怨。同样的,如果你这样做的话

let testSeq = seq { yield box A(0) yield upcast B(1)收益率上升C(2)}

根据第一个成员上次播放的类型推断 testSeq 为 seq< obj> code> obj ,而不是 A 。

I think I do not quite understand how F# infers types in sequence expressions and why types are not correctly recognized even if I specify the type of the elements directly from "seq".

In the following F# code we have a base class A and two derived classes, B and C:

type A(x) = member a.X = x type B(x) = inherit A(x) type C(x) = inherit A(x)

If I try to "yield" their instances in a simple sequence expressions, I get two errors:

// Doesn't work, but it makes sense. let testSeq = seq { yield A(0) yield B(1) // Error, expected type: A yield C(2) // Error, expected type: A }

That can make sense, since it may not be so trivial to infer "common" types (interfaces, I think, can make that work far harder). However, those errors can be fixed with a safe cast:

// Works fine :) let testSeqWithCast = seq { yield A(0) yield B(1) :> A yield C(2) :> A }

What if I do not want to use casts? I tried to specify the sequence type directly from "seq", but things do not seem to work:

// Should work, I think... let testGenSeq = seq<A> { yield A(0) yield B(1) // Error, expected type: A yield C(2) }

So, my question is: is there a way to avoid casts? If not, is there a reason why even specifying the type doesn't make the code work?

I tried digging through following links:

msdn.microsoft/en-us/library/dd233209.aspx lorgonblog.wordpress/2009/10/25/overview-of-type-inference-in-f/

But I found nothing useful...

Thank you in advance for any kind of answer you can give :)

解决方案

In order to understand the cause of your confusion you should not go anywhere further, than the first statement of the link you referred to :

A sequence is a logical series of elements all of one type.

You can return a sequence of only one, the same type like seq<A>, or seq<obj>. The OOP-ish fact that types B and C are inherited from A is not relevant. The following may help: all your instances are also inherited from obj, but in order to make from them a seq<obj> you should explicitly cast:

// Works fine let testSeq = seq<obj> { yield A(0) :> obj yield B(1) :> obj yield C(2) :> obj }

or just box them like below:

// Works fine too let testSeq = seq { yield box (A(0)) yield box (B(1)) yield box (C(2)) }

EDIT: For understanding the reasoning behind explicit casting in F# the following (simplistic) consideration may help. Type inference does not do guessing; unless it can derive seq type deterministically, or have it explicitly declared, it will complain.

If you just do

let testSeq = seq { yield A(0) yield B(1) yield C(2) }

compiler is presented with indeterminism - testSeq can be either seq<A>, or seq<obj>, so it complains. When you do

let testSeq = seq { yield A(0) yield upcast B(1) yield upcast C(2) }

it infers testSeq as seq<A> based on type of the first member and upcasts B and C to A without complaining. Similarly, if you do

let testSeq = seq { yield box A(0) yield upcast B(1) yield upcast C(2) }

it will infer testSeq as seq<obj> based on the type of the first member upcasting this time second and third members to obj, not A.

更多推荐

在F#中的序列表达式中输入推理

本文发布于:2023-11-17 03:11:24,感谢您对本站的认可!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:表达式   序列

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!