【问题标题】:F# and generics: can I have a collection of generic functions, each function having it's own generic type?F# 和泛型:我可以拥有一组泛型函数,每个函数都有自己的泛型类型吗?
【发布时间】:2020-12-14 17:21:27
【问题描述】:

我想定义一个这样的通用工作流程(简化)

type Fn1<'a> = RawInput -> 'a
type Fn2<'a> = 'a -> RawOutput
type Workflow<'a> = RoutingKey * Fn1<'a> * Fn2<'a>

type Workflows = Workflow list // <-- how to deal with it here?

我想过滤工作流,当我找到一个时,对其进行处理,以便每个人都可以拥有自己的'a

像上面这样的可能吗?如果没有,我可以使用哪些替代方案?


编辑

阐明问题:

我目前的工作流程只是RawInput -&gt; RawOutput,很好:

type Fn = RawInput -> RawOutput
type Workflow = RoutingKey * Fn
type Workflows = Workflow list

现在我需要介入并在每个工作流程的中间做一些“通用”的事情。所以决定将其拆分为两步函数,但现在我无法定义包含所有定义的集合。


编辑#2

试图更准确地解释我在做什么:原始工作流程需要拆分成多个部分并在中间“注入”一些通用代码,比如说:

type FnBefore<'a> = RawInput -> 'a 
// --I was wrong here: type FnVerify<'a> = 'a -> bool
type FnUniqueKey<'a> = 'a -> UniqueKey
type FnAfter<'a>  = 'a -> RawOutput
type Workflow<'a> = RoutingKey * FnBefore<'a> * FnUniqueKey<'a> * FnAfter<'a>
let workflows: Workflow list = […] // how can I declare'em all?

因此,从现在开始,每个工作流将定义 3 个函数而不是一个,并且我想将所有工作流保存在一个列表中,这样我就可以在每条新消息上选择一个(基于 RoutingKey)。 FnUniqueKey 应该为验证函数生成唯一密钥,以便在消息之前处理过时查找数据库。

【问题讨论】:

  • 简短的回答是这是不可能的,但为了提出替代方案,我们需要知道您最终想要做什么。这感觉就像XY problem
  • 我当前的工作流程只是SomeInput -&gt; SomeOutput,这很好,但现在我需要介入中间,在每个工作流程的中间做一些“通用”的事情。所以决定将其拆分为两步函数,但现在我无法定义包含所有定义的集合。
  • 你能举一个假设的例子来插入类似“通用”的东西吗?不编译也没关系,写点能表达思想的东西就行了。
  • 嗯,我最初的“工作流功能”想法很好,直到我意识到我需要处理消息重复。因此,在处理工作流程之前,我需要检查它是否已经被处理。 SomeInput 只是一个原始的 RabbitMQ 消息。每个工作流对其进行反序列化、处理和发布响应。我想在消息被反序列化和处理之前介入——这个反序列化的消息在我的例子中是'a
  • 好吧,如果你只是想在中间申请验证,为什么你需要知道中间的'a类型呢?每个工作流只能有一个函数RawInput -&gt; RawOutput option,其中返回None 表示验证失败。

标签: generics f#


【解决方案1】:

似乎没有办法创建这样的集合,我决定将'a隐藏起来,所以每个元素都会暴露两个函数,或多或少是这样的:

type UniqueKey = UniqueKey of string

type Workflow = // the 'a is hidden within, I cannot see it from here
    { UniqueKeyGetter: unit -> UniqueKey
      Exec           : unit -> RawOutput }

type MkWorkflow = RawInput -> Workflow

现在,我可以创建一个 RoutingKey * MkWorkflow 的集合,每个 MkWorkflow 将“创建一个工作流”,生成两个函数:

  • UniqueKeyGetter 将提供一个关闭从 RawInput 解码的未知对象的函数(这样我就可以检查唯一性)
  • Exec 将仅在工作流运行器给它开绿灯时使用(通过检查基于 UniqueKey 的已处理工作流的数据库

现在我真的可以隐藏'a了。这个MkWorkflow 让我有点害怕,不过,它是 OOP 框架的“SometingFactoryProxyProducerGenerator”地狱中的一步。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多