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

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

问题描述

背景:这是功能性DI的变体。遵循斯科特的文章,我写了一篇翻译。问题的关键在于我的解释器是通用的,并且参数化是基于你所提供的。



为了测试的目的,我想通过另一个解释器,其中有谎言擦 - 我怎么样?以下是问题的简要概述:

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

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

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

你不能这样做在F#中有函数。函数在作为值传递时会失去通用性。



然而,F#确实有一个机制来完成它,尽管有点笨拙:接口。接口方法可以是通用的,所以你可以使用它们来包装泛型函数:

  type Wrapper = 
abstract member F<'一> :'a - > 'a

让y(w:Wrapper)=
让a = wf 1
让b = wf 2L
(a,b)

let genericFn x = x

//调用y:
y {new包装带成员__。fx = genericFn x}

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

  let mkWrapper f = 
// no can do:`f`此时会被限制为一个非泛型类型
{new成员包含__。fx = fx}

但是您可以为另一方提供一些便利。至少摆脱了类型注释:

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

let callF(w:Wrapper)x = wf x

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

上面的代码中可能会有一些小的语法错误,正如我在手机上写的那样)


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 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).

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

解决方案

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

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天全站免登陆