这个问题似乎很愚蠢,但我在网上找不到任何类似的内容。所以我走了。
我需要使用类似Collection的结构,该结构应用作Map中的值。该集合具有泛型类型,并且映射应包含这些集合中的任何一种(int,boolean,string等)。鉴于这不可能直接实现(由于在Map定义中将通用类型限制为唯一值),我使用了一个辅助DU来匹配所有情况(假设它们很少)。我的问题是我想编写一个通用函数,该函数接收HOF并在类似于Collection的数据结构上执行,而与内部通用类型无关,但我不能;这是说明问题的简单代码:
type EspecificList =
| IntList of int list
| BoolList of bool list
let listLength = function
| IntList list -> List.length list
| BoolList list -> List.length list
let listGenericFunc func = function
| IntList list -> func list
| BoolList list -> func list
listLength可以正常工作,但listGenericFunc不能工作; func
专门针对第一种类型,而错误则针对第二种:添加诸如(func: List<'a> -> 'b)
之类的通用类型注释也不起作用。
有什么办法可以避免这种情况并保持该函数的通用精神?我可能会错过一些确实很明显的东西,但看不到。
谢谢!
编辑
好的,我继续了最近的几天的研究,尽管我计划提交有关我的特定域问题的更详细的问题,但我想分享我遇到的可能解决方案,并询问是否认为有他们中的一些或多或少是沙哑的。我将按照找到它们的顺序列出解决方案。
1。 WalternativE响应
每种可能的类型将函数传递n次;带有或不带有类型注释
let listGenericFunc (func: bool list -> 'b) (func': int list -> 'b) = function
| BoolList list -> func list
| IntList list -> func' list
listGenericFunc List.length List.length (IntList [1;2])
2。静态成员和内联魔术
使用静态的“ apply”成员并为每个可能的函数定义类型,并与内联的“ applyer”一起使用。
type ListLength = ListLength with static member ( $ ) (ListLength,x) = x |> List.length
let inline applier f x = f $ x
let listGenericFuncInline func = function
| IntList list -> applier func list
| BoolList list -> applier func list
listGenericFuncInline ListLength (IntList [1; 2; 3]) // return 3
listGenericFuncInline ListLength (BoolList [true; false]) // return 2
这是对这一特定SO question
的回应3。隐藏的通用类型
从最后一个问题中,我发现了存在类型,并偶然发现了this article。仅使用有关通用类型的文章的第一部分就可以完成我想要的事情。
type UListFuncs<'ret> = abstract member Eval<'a> : ('a list) -> 'ret
let listLength : UListFuncs<int> =
{ new UListFuncs<int> with
member __.Eval<'a> (x : 'a list) = x |> List.length }
let listGenericFuncUniversal (func : UListFuncs<'a>) = function
| IntList list -> func.Eval list
| BoolList list -> func.Eval list
listGenericFuncUniversal listLength (IntList [1; 2; 3]) // return 3
listGenericFuncUniversal listLength (BoolList [true; false]) // return 2
印象
我不知道哪个是最好的选择;我觉得第二个函数有点尴尬,因为每个函数都需要这种类型。无论添加了什么样板,我都真的很喜欢第三个(这篇文章很好地解释了,阅读起来也很有趣)。你有什么想法?