具有特定属性的记录类型的F#类型约束 [英] F# type constraint for record type with specific property

查看:105
本文介绍了具有特定属性的记录类型的F#类型约束的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图创建一个泛型函数,它需要它的类型参数,它是一个记录类型,并且它有一个特定的属性。以下是一个生成相关编译器错误的示例:

  let foo< a> (a:'a)= 
a'= {a with bar =baz}
a'

编译此错误,我得到一个错误,指出记录标签栏未定义



我尝试添加下面的类型约束:

  let foo<'a when a:(member Id:string)> = 
// ...

但也没有编译,抱怨这段代码不够通用。当^ a :(成员get_Int:^ a - >字符串)时,类型变量^ a不能被泛化,因为它会转义它的作用域。



有没有一种方法可以指定一个类型约束条件,让我可以正确地做到这一点? 我会建议阅读Tomas '先回答。尽可能避免使用静态解析的类型约束。它们是F#编译器的一个特性,而不是.NET,所以它们在一定程度上限制了代码的可重用性。也就是说,它们非常强大,并且允许你在编译时施加有用的约束。



使用它们的语法也不是非常令人愉快,但如果你仍然没有被捕获,你可以做这样的事情:

  type Test = {Bar:string} 

let inline foo (a:^ a)=
foo+((^ a):(member Bar:string)(a))

let foobar = foo {Bar =bar} //打印foo bar

请注意,您实际上无法将类型限制为记录,只是包含字符串类型的成员 Bar 的内容。所以这也解决了:

  type Test2(str:string)= member this.Bar = str 

let foobar2 = foo(Test2(bar))//打印foo bar


I'm trying to create a generic function which requires of its type argument that it is a record type, and that it has a specific property. Here's a sample that generates the relevant compiler error:

let foo<'a> (a : 'a) =
    a' = { a with bar = "baz" }
    a'

Compiling this I get an error stating The record label bar is not defined.

I tried adding the following type constraint:

let foo<'a when 'a : (member Id : string)> =
    // ...

but that didn't compile either, complaining that This code is not sufficiently generic. The type variable ^a when ^a : (member get_Int : ^a -> string) could not be generalized because it would escape its scope.

Is there a way to specify a type constraint that would let me do this properly?

解决方案

I would suggest reading Tomas' answer first. Using statically resolved type constraints should generally be avoided when possible. They're a feature of the F# compiler rather than .NET so they do, to some extent, restrict the reusability of your code. That said, they are very powerful and do allow you to impose useful constraints at compile time.

The syntax for using them is also not terribly pleasant but if you remain undeterred, you could do something like this:

type Test = {Bar : string}

let inline foo (a : ^a) =
    "foo " + ((^a) : (member Bar : string) (a))

let foobar = foo {Bar = "bar"} // prints "foo bar"

Note however that you can't actually restrict the type to being a record, simply something that has a member Bar of type string. So this would also resolve:

type Test2(str : string) = member this.Bar = str

let foobar2 = foo (Test2("bar")) // prints "foo bar"

这篇关于具有特定属性的记录类型的F#类型约束的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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