繁体   English   中英

F# 模块中的通用值?

[英]Generic values in F# modules?

考虑一个通用容器,如:

type Foo<'t> = 
  {
    Foo : 't
  }

这个通用函数可以正常工作:

module Foo = 
  
  let inline emptyFoo () = 
    {
      Foo = LanguagePrimitives.GenericZero
    }

但是这个值不会:

module Foo = 
  
  let emptyFoo = 
    {
      Foo = LanguagePrimitives.GenericZero
    }

这是因为编译器推断emptyFoo具有Foo<obj>类型。

然而,标准库有像List.empty这样的通用值,那么它是如何实现的呢?

您必须使其明确通用。

List.empty实现像这样

let empty<'T> = ([ ] : 'T list)

你可以自己实现一个 List ,一个空的。 它看起来像这样。

type L<'a> =
    | Null
    | Cons of 'a * L<'a>

module L =
    let empty = Null

let xs = Cons(1,  Cons(2,  L.empty))
let ys = Cons(1.0,Cons(2.0,L.empty))

那么,为什么L.empty在这种情况下以通用方式工作? 因为值Null没有附加任何特殊值。 你可以说,它与所有其他泛型兼容。

另一方面,在您的 Record 中,您始终必须产生一个值。 LanguagePrimitive.GenericZero不是一些 Generic 值。 解析为一个特殊的零值是有帮助的,这个值是由你编写的其他代码决定的。

例如

let x = LanguagePrimitives.GenericZero

也是obj

let x = LanguagePrimitives.GenericZero + 1

将是int

let x = LanguagePrimitives.GenericZero + 1.0

float 因此,在某些情况下,您可以将GenericZero视为您需要的特殊类型的零占位符,但此时代码需要确定您想要哪种类型。

您可以更改您的类型,并选择提供一个真正的空。

type Foo<'t> = {
    Foo: 't option
}

module Foo =
    let empty = { Foo = None }

let x = Foo.empty                  // Foo<'a>
let y = { x with Foo = Some 1   }  // Foo<int>
let z = { x with Foo = Some 1.0 }  // Foo<float>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM