gpt4 book ai didi

f# - 静态解析的类型成员约束无法识别系统类型的扩充

转载 作者:行者123 更新时间:2023-12-04 23:02:56 24 4
gpt4 key购买 nike

为了更好地使用 F# 并更好地理解 Suave.io 的工作原理,我一直在尝试创建一些可重用的函数/运算符来组合函数。我知道 Suave 实际上实现了它的 >=> 运算符来专门为异步选项工作,但我认为尝试和概括它会很有趣。

下面的代码受到了太多值得信任的来源的启发,它适用于我自己定义的类型,但我不能让它适用于系统类型。即使 Nullable 和 Option 的类型扩充编译得很好,它们也不会被识别为与绑定(bind)函数中的成员约束匹配。

当我未能使其适用于 Option 时,我曾希望这可能是因为 Option 在 F# 中很特殊,这就是我尝试使用 Nullable 的原因,但遗憾的是,没有雪茄。

fsi 的相关错误和输出在注释中的以下代码中。

任何帮助,将不胜感激。

谢谢,
约翰

open System

let inline bind (f : ^f) (v : ^v) =
(^v : (static member doBind : ^f * ^v -> ^r )(f, v))
// I'd prefer not having to use a tuple in doBind, but I've
// been unable to make multi arg member constraint work

let inline (>=>) f g = f >> (bind g)

// Example with Result
type public Result<'a,'b> =
| Success of 'a
| Error of 'b

type public Result<'a,'b> with
static member inline public doBind (f, v) =
match v with
| Success s -> f s
| Error e -> Error e

let rF a = if a > 0 then Success a else Error "less than 0"
let rG a = if a < 10 then Success a else Error "greater than 9"

let rFG = rF >=> rG
// val rFG : (int -> Result<int,string>)

//> rFG 0;;
//val it : Result<int,string> = Error "less than 0"
//> rFG 1;;
//val it : Result<int,string> = Success 1
//> rFG 10;;
//val it : Result<int,string> = Error "greater than 9"
//> rFG 9;;
//val it : Result<int,string> = Success 9

// So it works as expected for Result

// Example with Nullable

type Nullable<'T when 'T: (new : unit -> 'T) and 'T: struct and 'T:> ValueType> with
static member inline public doBind (f, v: Nullable<'T>) =
if v.HasValue then f v.Value else Nullable()

let nF a = if a > 0 then Nullable a else Nullable()
let nG a = if a < 10 then Nullable a else Nullable()
let nFG = nF >=> nG
// error FS0001: The type 'Nullable<int>' does not support the operator 'doBind'


type Core.Option<'T> with
static member inline doBind (f, v) =
match v with
| Some s -> f s
| None -> None


let oF a = if a > 0 then Some a else None
let oG a = if a < 10 then Some a else None

let oFG = oF >=> oG
// error FS0001: The type 'int option' does not support the operator 'doBind'

最佳答案

为什么在静态成员约束中不考虑扩展方法是一个已经被问过很多次的问题,并且肯定会继续被问到,直到该功能在 F# 编译器中实现。

this related question带有指向其他相关问题的链接以及指向 F# 编译器中必须执行的操作以支持此功能的详细说明的链接。

现在,对于您的具体情况,那里提到的解决方法可以解决您的问题,并且已经在 FsControl 中实现.

这是代码:

#nowarn "3186"
#r "FsControl.dll"

open FsControl.Operators

// Example with Result
type public Result<'a,'b> =
| Success of 'a
| Error of 'b

type public Result<'a,'b> with
static member Return v = Success v
static member Bind (v, f) =
match v with
| Success s -> f s
| Error e -> Error e

let rF a = if a > 0 then Success a else Error "less than 0"
let rG a = if a < 10 then Success a else Error "greater than 9"

let rFG = rF >=> rG
// val rFG : (int -> Result<int,string>)

rFG 0
//val it : Result<int,string> = Error "less than 0"
rFG 1
//val it : Result<int,string> = Success 1
rFG 10
//val it : Result<int,string> = Error "greater than 9"
rFG 9
//val it : Result<int,string> = Success 9

// So it works as expected for Result


// Example with Option

let oF a = if a > 0 then Some a else None
// val oF : a:int -> int option

let oG a = if a < 10 then Some a else None
// val oG : a:int -> int option

let oFG = oF >=> oG
// val oFG : (int -> int option)

oFG 0
// val it : int option = None

oFG 1
// val it : int option = Some 1

无论如何,我建议使用现有的 Choice而不是成功/错误或 implementing Success on top of Choice在你的情况下,它会是这样的:
type Result<'a, 'b> = Choice<'a, 'b>
let Success x :Result<'a, 'b> = Choice1Of2 x
let Error x :Result<'a, 'b> = Choice2Of2 x
let (|Success|Error|) = function Choice1Of2 x -> Success x | Choice2Of2 x -> Error x

然后您可以运行您的示例而无需编写任何绑定(bind)或返回。

您可能想知道为什么没有 Nullable 的示例,那只是因为 Nullable不是 monad,它只适用于值类型,函数不是值类型,所以最好坚持 Option对于相同的功能。

关于f# - 静态解析的类型成员约束无法识别系统类型的扩充,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39006587/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com