如何将 LanguagePrimitives.GenericZero / get_Zero 添加到 System.String?

2023-11-26

注:我添加了很多Of interest评论在最后。这些并不意味着建议人们应该使用inline and static type parameters 无论如何,它们就在那里,这样人们就不必花费数小时搜索与此问题相关的大量 SO 问题来更好地理解这些概念。

我知道,当需要使函数通用并需要零 (0) 值时,F# 提供了通用零.

解析为任何原始数值类型或任何类型的零值 带有一个名为 Zero 的静态成员。

所以这让我相信使用GenericZero对于字符串类型,我只需添加一个名为 Zero 的静态成员。

Since 系统字符串是.Net框架的一部分,修改.Net源代码不是应该做的事情。然而 F# 提供了类型扩展.

类型扩展允许您向先前定义的对象添加新成员 类型。

F# 还提供了字符串模块,但是缺少 GenericZero。

有关创建类型扩展的良好教程参考:将函数附加到类型.

我测试的代码:

这是在一个名为Library1

namespace Extension.Test

module Extensions = 

    type System.String with
        static member Something = "a"

        static member StaticProp
            with get() = "b"

        static member Zero
            with get() = "c"

这是在一个名为Workspace

namespace Extension.Test
module main =

    open Extensions

    [<EntryPoint>]
    let main argv = 

        let stringSomething = System.String.Something
        printfn "something: %s" stringSomething

        let staticProperty = System.String.StaticProp
        printfn "staticProperty: %s" staticProperty

        let zeroProperty = System.String.Zero
        printfn "zeroProperty: %s" zeroProperty

        let inline addTest (x : ^a) (y : ^a) : ^a =
            x + y

        let intAdd = addTest 2 LanguagePrimitives.GenericZero
        let floatAdd = addTest 2.0 LanguagePrimitives.GenericZero
//        let stringAdd = addTest "a" LanguagePrimitives.GenericZero

        printfn "intAdd: %A" intAdd
        printfn "floatAdd: %A" floatAdd
//        printfn "stringAdd: %A" stringAdd

        printf "Press any key to exit: "
        System.Console.ReadKey() |> ignore
        printfn ""

        0 // return an integer exit code

运行时输出:

something: a
staticProperty: b
zeroProperty: c
intAdd: 2
floatAdd: 2.0
Press any key to exit

因此,我可以毫无问题地创建和访问扩展成员并使用 GenericZero。

最后一部分是使用 GenericZero 作为字符串,但是取消注释该行

let stringAdd = addTest "a" LanguagePrimitives.GenericZero

结果出现错误:

类型“string”不支持运算符“get_Zero”

我确实检查了F# spec但没有找到任何帮助。

我可以添加 GenericZero 来输入吗System.String,我在代码中做错了什么,还是我错过了文档中的某些内容?

TL;DR

搜索时感兴趣的问题

F# - 如何使用 get_Zero 扩展类型,以便可以通用地使用现有类型?
IMO 是一个误导性的标题,应该在阅读答案后更改。

F# 的 int 中的 get_Zero 是什么/在哪里?
杰克有一个很好的评论:

如果你从以下角度思考的话,零在字符串上没有意义 数字;但是,字符串上有一个零成员确实有意义 它返回空字符串,因为这会使字符串成为幺半群 在字符串连接下。

感兴趣的 F# 文档

自动泛化

F# 编译器在对函数执行类型推断时, 确定给定参数是否可以是通用的。编译器 检查每个参数并确定该函数是否具有 依赖于该参数的特定类型。如果没有,则 类型被推断为通用的。

类型推断

类型推断的想法是您不必指定 F# 构造的类型,除非编译器无法最终确定 推导类型。

对于那些你没有显式指定的类型,编译器 根据上下文推断类型。如果类型不是其他类型 指定,则推断它是通用的。

Generics

F# 函数值、方法、属性和聚合类型,例如 类、记录和可区分联合可以是通用的。通用的 构造体至少包含一个类型参数,通常是 由通用构造的用户提供。通用函数和 类型使您能够编写适用于各种类型的代码 无需为每种类型重复代码。使您的代码具有通用性 在 F# 中要简单,因为您的代码通常会被隐式推断为 通过编译器的类型推断和自动泛化实现泛型 机制。

静态解析类型参数

静态解析的类型参数是这样的类型参数 在编译时而不是在运行时替换为实际类型。 它们前面有插入符号 (^)。

静态解析的类型参数是主要用于 与成员约束相结合,这是允许的约束 您指定类型参数必须具有特定成员或 会员才能使用。没有办法创建这种类型 使用常规泛型类型参数进行约束。

在 F# 语言中,有两种不同类型的参数。 第一种是标准泛型类型参数。这些都是 用撇号 (') 表示,如 'T 和 'U。它们是等价的 到其他 .NET Framework 语言中的泛型类型参数。这 另一种是静态解析的,并由插入符号指示, 如 ^T 和 ^U 所示。

约束条件

内联函数

当您使用静态类型参数时,任何函数 由类型参数化的参数必须是内联的.

EDIT

这是一个使用的示例GenericZero对于用户定义的类型,无需使用有效的扩展,并且有两个变体表明GenericZero不适用于intrinsic extension and optional extension

先运行程序看看GenericZero工作然后取消注释行Program.fs查看错误intrinsic extension and optional extension.

An 内在延伸是出现在相同的扩展名 命名空间或模块,位于同一源文件和同一程序集中 (DLL 或可执行文件)作为被扩展的类型。

An 可选扩展是出现在外部的扩展名 正在扩展的类型的原始模块、命名空间或程序集。 当类型被检查时,内在扩展出现在类型上 反射,但可选扩展则不然。可选扩展必须 位于模块中,并且仅当模块 包含扩展名已打开。

In Library1.fs在项目中Library1

namespace Extension.Test

module module001 = 

    // No extension
    type MyType01(x: string) =
        member this.x = x

        override this.ToString() = this.x.ToString()

        static member Something = MyType01("a")        
        static member (+) (mt1 : MyType01, mt2 : MyType01) = MyType01(mt1.x + mt2.x)
        static member (+) (mt1 : MyType01, s : string) = MyType01(mt1.x + s)
        static member (+) (s : string, mt2 : MyType01) = MyType01(s + mt2.x)

        static member Zero
            with get() = MyType01("b")

    // uses intrinsic extension
    type MyType02(x: string) =
        member this.x = x

        override this.ToString() = this.x.ToString()

        static member Something = MyType02("g")        
        static member (+) (mt1 : MyType02, mt2 : MyType02) = MyType02(mt1.x + mt2.x)
        static member (+) (mt1 : MyType02, s : string) = MyType02(mt1.x + s)
        static member (+) (s : string, mt2 : MyType02) = MyType02(s + mt2.x)

//        static member Zero
//            with get() = MyType02("h")

    // uses optional extension
    type MyType03(x: string) =
        member this.x = x

        override this.ToString() = this.x.ToString()

        static member Something = MyType03("m")        
        static member (+) (mt1 : MyType03, mt2 : MyType03) = MyType03(mt1.x + mt2.x)
        static member (+) (mt1 : MyType03, s : string) = MyType03(mt1.x + s)
        static member (+) (s : string, mt2 : MyType03) = MyType03(s + mt2.x)

//        static member Zero
//            with get() = MyType03("n")


module module002 = 

    open module001

    // intrinsic extension
    type MyType02 with

        static member Zero
            with get() = MyType02("h")

in Library2.fs在项目中Library2

namespace Extension.Test

open module001

module module003 = 

    type MyType01 with 

        static member Anything = MyType02("c")

    type MyType02 with 

        static member Anything = MyType02("i")

    // optional extension
    type MyType03 with 

        static member Anything = MyType03("p")

        static member Zero
            with get() = MyType03("n")

in Program.fs在项目中Workspace

namespace Workspace

open Extension.Test.module001
open Extension.Test.module002
open Extension.Test.module003

module main =

    [<EntryPoint>]
    let main argv = 


        let staticFromBaseType = MyType01.Something
        printfn "MyType01 staticFromBaseType: %A" staticFromBaseType

        let staticFromExtensionType = MyType01.Anything
        printfn "MyType01 staticFromExtensionType: %A" staticFromExtensionType

        let zeroValue = MyType01.Zero
        printfn "MyType01 zeroValue: %A" zeroValue

        let (genericZero: MyType01) = LanguagePrimitives.GenericZero
        printfn "MyType01 genericZero: %A" genericZero

        let staticFromBaseType = MyType02.Something
        printfn "MyType02 staticFromBaseType: %A" staticFromBaseType

        let staticFromExtensionType = MyType02.Anything
        printfn "MyType02 staticFromExtensionType: %A" staticFromExtensionType

        let zeroValue = MyType02.Zero
        printfn "MyType02 zeroValue: %A" zeroValue

//        let (genericZero: MyType02) = LanguagePrimitives.GenericZero
//        printfn "MyType02 genericZero: %A" genericZero


        let staticFromBaseType = MyType03.Something
        printfn "MyType03 staticFromBaseType: %A" staticFromBaseType

        let staticFromExtensionType = MyType03.Anything
        printfn "MyType03 staticFromExtensionType: %A" staticFromExtensionType

        let zeroValue = MyType03.Zero
        printfn "MyType03 zeroValue: %A" zeroValue

//        let (genericZero: MyType03) = LanguagePrimitives.GenericZero
//        printfn "MyType03 genericZero: %A" genericZero

        let inline addTest (x : ^a) (y : ^a) : ^a =
            x + y

        let intAdd = addTest 2 LanguagePrimitives.GenericZero
        let floatAdd = addTest 2.0 LanguagePrimitives.GenericZero
        let (myType01Add : MyType01) = addTest (MyType01("d")) LanguagePrimitives.GenericZero
//        let (myType02Add : MyType02) = addTest (MyType02("d")) LanguagePrimitives.GenericZero
//        let (myType03Add : MyType03) = addTest (MyType03("o")) LanguagePrimitives.GenericZero

        printfn "intAdd:      %A" intAdd
        printfn "floatAdd:    %A" floatAdd
        printfn "myType01Add: %A" myType01Add
//        printfn "myType02Add: %A" myType02Add
//        printfn "myType03Add: %A" myType03Add


        printf "Press any key to exit: "
        System.Console.ReadKey() |> ignore
        printfn ""

        0 // return an integer exit code

扩展成员不被视为成员约束解析的一部分,所以你运气不好。对于涉及多种类型的约束(例如对(+)),您可以通过使用第二种类型来解决这个问题,但是对于GenericZero没有好的解决方法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将 LanguagePrimitives.GenericZero / get_Zero 添加到 System.String? 的相关文章

随机推荐

  • 旋转和裁剪

    我正在使用 PHP 旋转和裁剪图像 但显示黑色边框 我知道您可以更改背景颜色 但我想旋转和裁剪图像以填充整个图像 基本上类似于background size cover 左 CSS 与background size contain 正确的
  • Python 无法找到 lxml 模块

    我前段时间写了一个脚本 其中包含 from lxml import etree 但是 不幸的是它不再起作用了 如有疑问 我检查了安装 sudo apt get install python lxml sudo pip install lxm
  • 如何配置 iText 支持亚洲字符?

    我的 Java 应用程序使用 iText 创建 PDF 有时内容是亚洲的 这是行不通的 亚洲字符不可见 I found iTextAsian jar在iText下载页面上 但不知道如何使用它 目标是使用我最喜欢的字体作为默认字体 但是 当某
  • SignalR 2.0 超时连接

    我正在使用SignalR 但是存在超时问题 几分钟后超时消失 不起作用 我怎么能够在 SignalR 2 0 中设置超时连接 您可以在 Owin Startup 类中使用以下配置 Make long polling connections
  • 使用其他 Observable 过滤 RxJava Observable

    我正在使用 RxAndroid 2 0 1 和 RxJava 2 0 6 我有两个可观察量 一个返回Maybe
  • onClickListener 和 onItemClickListener 之间的区别

    Android ListViews 中的 onClickListener 和 onItemClickListener 有什么区别 这些有哪些不同的实现 ListView 为列表视图的每一行都有一个 Item Click 侦听器 但 onCl
  • Python 和 Selenium - 当带有换行符的 send_keys() 时避免提交表单

    我在用Python 3与硒 我们假设var whatever nelse 我的问题是当我使用elem send keys var 它在之后发送表格 任何 因为换行符 我如何将 whatever nelse 替换为whatever SHIFT
  • GraphHopper 车辆=汽车可以工作,但步行或自行车不起作用

    我对 GraphHopper 路由引擎稳定版本 0 5 有疑问 我可以在使用时获取路线vehicle car 但这失败了bike and foot 这是一个例子在 GraphHopper 地图上步行大约 3 分钟 这会在地图上产生结果 非常
  • 如何重写祖先的嵌套 Material UI 组件的样式?

    我正在使用外部库中的组件 该组件不允许我更改其大部分样式 但我想更改作为材质 ui 按钮的按钮的样式 在检查元素时 它清楚地显示了类MuiButtonBase root MuiIconButton root MuiIconButton co
  • asp.net-mvc:js文件中的剃刀'@'符号

    我有一个 csHtml razor 文件 其中包含一个 javascript 函数 该函数使用 Url ContentAjax URL 内部的 C 函数 我想将该功能移至 js从我的观点引用的文件 问题是 javascript 不 知道 符
  • OpenCv StereoRectify 中矩阵的精确定义

    通常投影矩阵的定义P是 3x4 矩阵 它将点从世界坐标投影到图像 像素坐标 投影矩阵可以分解为 K 具有内在参数的 3x4 相机矩阵 K T 带有外部参数的 4x4 变换矩阵 那么投影矩阵就是P K T OpenCV 的stereoRect
  • 我可以使用 jquery post 来上传图片吗?

    我正在尝试使用 jquery 来提交我的表单 但它不会触发functions php 文件中的任何内容 我需要对 multipart form data 做一些特别的事情吗 我错过了什么吗 HTML
  • iPhone 动画基于输入值(触摸)而不是时间

    对于完全适合动画组方法的动画效果 如下所示布拉德 拉尔森的回答在这里 我需要动画根据输入进行 特别是触摸和检测到的触摸的位置 处理 TouchMoved 并为每次触摸设置元素的位置很容易 但它不像核心动画方法那样平滑 想象一下有凹槽的轨道上
  • Pandas 删除数据框中指定字符后的字符串部分

    我想要一种简单的方法来删除数据框中特定字符之后的字符串部分 这是一个简化的示例 df obs a b c d 0 1 1 23 12 1 2 3 1 2 12 23 13 4 5 5 2 3 21 23 14 4 5 5 我想删除第一个 符
  • 设置 Google Play 游戏服务

    我最近一直在尝试新的 Google Play 游戏服务 我花了一些时间来设置所有内容以使示例项目运行 主要是因为a犯了很多小错误 因此 我写了一个小清单 这样其他人就不必经历同样的结果 开发很有趣 配置则不然 谷歌对此有一个很好的快速入门
  • 如何管理 ASP.NET WebApi2 中的缓存?

    我已经使用 Web API 2 实现了 REST 服务 该服务的实现是为了管理由访问服务的不同客户端创建和加入的不同会话 会话包含有关应用程序功能访问的信息以及已加入同一会话的参与者的信息 每个客户端每秒从服务器获取会话信息和访问列表以进行
  • Spark 中优雅的 Json 扁平化 [重复]

    这个问题在这里已经有答案了 我在 Spark 中有以下数据框 val test sqlContext read json path path to jsonfiles test printSchema root properties str
  • 只写属性有实际应用吗?

    我不知道为什么我开始思考这个问题 但现在我似乎无法停止 在 C 中 可能还有很多其他语言 我记得 Delphi 也曾经让你这样做 编写以下语法是合法的 class WeirdClass private void Hello string n
  • 为什么password_verify返回false?

    我在用着password verify检查我的哈希密码 我有 PHP 5 5 get result row as an object result row result of login check gt fetch object usin
  • 如何将 LanguagePrimitives.GenericZero / get_Zero 添加到 System.String?

    注 我添加了很多Of interest评论在最后 这些并不意味着建议人们应该使用inline and static type parameters 无论如何 它们就在那里 这样人们就不必花费数小时搜索与此问题相关的大量 SO 问题来更好地理