传递解析为多种类型的泛型函数的最佳方法是什么 [英] What is the best way to pass generic function that resolves to multiple types

查看:19
本文介绍了传递解析为多种类型的泛型函数的最佳方法是什么的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景:这是功能性 DI 的变体.根据 Scott 的帖子,我写了一个口译员.不同的是,我的解释器是通用的,并且根据你提供给它的内容进行参数化.

For the background: It's a variation on functional DI. Following Scott's post I wrote an interpreter. The twist is that my interpreter is generic and parametrized based on what you feed to it.

出于测试目的,我想传递另一个解释器,这就是问题所在 - 我该怎么做?以下是问题的简化概述:

For testing purposes I'd like to pass another interpreter in, and therein lies the rub - how can I? Here's the simplified outline of the problem:

let y f =
    let a = f 1
    let b = f 2L
    (a,b)

f 是我的通用解释器,但在这里它显然受限于第一次使用 int ->'一个.在这个简化的场景中,我可以只传递解释器两次,但在我的实际实现中,类型空间相当大(基本类型 x3 输出类型).

f is my generic interpreter, but here it is obviously constrained by the first use to int -> 'a. In this simplified scenario I could just pass the interpreter twice, but in my actual implementation the type space is rather large (base type x3 output types).

是否有一些 F# 机制可以让我这样做,而没有太多的开销?

Is there some F# mechanism that would let me do that, w/o too much overhead?

推荐答案

您无法在 F# 中使用函数执行此操作.函数作为值传递时失去通用性.

You can't do this in F# with functions. Functions lose genericity when passed as values.

然而,F# 确实有一种机制可以做到这一点,尽管有点笨拙:接口.接口方法可以是通用的,因此您可以使用它们来包装您的通用函数:

However, F# does have a mechanism for doing it anyway, albeit a bit awkwardly: interfaces. Interface methods can be generic, so you can use them to wrap your generic functions:

type Wrapper =
    abstract member f<'a> : 'a -> 'a

let y (w: Wrapper) = 
   let a = w.f 1 
   let b = w.f 2L 
   (a, b)

let genericFn x = x

// Calling y:
y { new Wrapper with member __.f x = genericFn x }

缺点是,你不能回到高阶函数,以免失去通用性.你必须有一直到海龟的接口.例如,您不能通过将其抽象为函数来简化实例创建:

The downside is, you can't go back to higher-order functions, lest you lose genericity. You have to have interfaces all the way down to the turtles. For example, you can't simplify the instance creation by abstracting it as a function:

let mkWrapper f = 
   // no can do: `f` will be constrained to a non-generic type at this point
   { new Wrapper with member __.f x = f x }

但你可以在另一方面提供一些便利.至少去掉类型注释:

But you can provide some convenience on the other side. At least get rid of type annotations:

type Wrapper = abstract member f<'a> (x: 'a): 'a

let callF (w: Wrapper) x = w.f x

let y w = 
   let a = callF w 1 
   let b = callF w 2L 
   (a,b)

(注意:上面的代码可能有轻微的语法错误,因为我是在手机上写的)

(NOTE: there may be minor syntactic mistakes in the above code, as I'm writing on my phone)

这篇关于传递解析为多种类型的泛型函数的最佳方法是什么的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆