2

我想创建一个流,从传入的元素中创建一个新的源(它将是一个持久性查询),然后将结果展平。像这个简化的例子:

var z = Source.Single(1).ConcatMany(i => Source.Single(i));

此代码按预期编译和工作。我的问题是,当我将它翻译成 F# 时:

let z = Source.Single(1).ConcatMany(fun i -> Source.Single(i))

我收到一条错误消息

This expression was expected to have type
    'IGraph<SourceShape<'a>,Akka.NotUsed>'    
but here has type
    'Source<int,Akka.NotUsed>'    

我认为其原因是 F# 处理协/逆变的方式与 C# 不同,并且不能简单地转换这些通用专业化(https://github.com/fsharp/fslang-suggestions/issues/162),但我无法弄清楚在 anint和 a之间进行转换的方法SourceShape<int>。是否可以将此示例转换为 F#?

4

2 回答 2

2

查看GitHub 上的代码,它似乎Source<TOut, TMat>是 的直接实现IGraph,因此您应该能够转换它:

public sealed class Source<TOut, TMat> : IFlow<TOut, TMat>, IGraph<SourceShape<TOut>, TMat>

let z = Source.Single(1).ConcatMany(fun i -> Source.Single(i) :> IGraph<SourceShape<int>,Akka.NotUsed>)

我认为 C# 和 F# 用法之间的最大区别在于 C# 会自动为您进行向上转换。

于 2019-10-22T13:13:53.427 回答
1

我发现的一种解决方法是使用Akkling.Streams包装库:

open Akkling.Streams

let x =
    Source.singleton 1
    |> Source.collectMap(fun x -> Source.singleton x)

如何在没有 Akkling 的情况下做到这一点的问题仍然悬而未决。

于 2019-10-21T10:35:16.850 回答