gpt4 book ai didi

f# - 我可以在单例区分联合中调用 "aliased"类型的方法吗?

转载 作者:行者123 更新时间:2023-12-01 13:59:40 26 4
gpt4 key购买 nike

我在优秀的 F# for Fun and Profit 中读到,我可以使用单案例区分联合来获得类型安全等。所以我试着这样做。但是我很快发现我无法调用被 DU(有点)别名或查看的类型的方法。

这是一个例子:

type MyList = MyList of List<int>
let list' = [1; 2; 3]
printfn "The list length is %i" list'.Length
let myList = MyList([1; 2; 3])
// The list length is 3
// type MyList = | MyList of List<int>
// val list' : int list = [1; 2; 3]
// val myList : MyList = MyList [1; 2; 3]

到目前为止一切顺利。然后我试了一下

myList.Length
// Program.fs(12,8): error FS0039: The field, constructor or member 'Length' is not defined.

当使用单例 DU 时,是否有一种简单的方法来访问“别名”或“已查看”类型的方法?

最佳答案

这不是您所说的“别名”。您已经声明了一个全新的类型,其中包含一个列表。您的类型不仅仅是列表的另一个名称,它是一个包装器。

如果你想声明一个真正的别名,你应该使用语法type A = B ,例如:

type MyList = List<int> 
let myList : MyList = [1; 2; 3]
printf "Length is %d" myList.Length

有了这样的别名,MyList将 100% 替代 List<int>反之亦然。这就是通常所说的“别名”。同一事物的不同名称。

另一方面,包装器将为您提供额外的类型安全性:如果您尝试使用裸List<int>,编译器将捕获。其中 MyList是期待。这就是通常使用此类包装器的方式。但是这种额外的保护是有代价的:你不能只使用 MyList就好像它是一个列表。因为那会扼杀整个想法。不能两全其美。

问:等等,你的意思是说我必须重新实现所有列表功能才能获得这个包装器吗?

嗯,不。如果你从方法转移到函数,你可以通过提供 map 来使这个包装/解包通用。 :

type MyList = MyList of List<int>
with static member map f (MyList l) = f l

let myList = MyList [ 1; 2; 3 ]
let len = MyList.map List.length myList

如果您发现自己经常使用某个特定功能,您甚至可以给它起一个自己的名字:

let myLen = MyList.map List.length
let len = myLen myList

Here是 Wlaschin 先生关于该主题的另一篇文章。

另请注意:这是方法不如函数的另一种方式。人们通常会尽可能避免方法。

关于f# - 我可以在单例区分联合中调用 "aliased"类型的方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43047756/

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