我正在尝试弄清楚包含在rop结果中的泛型类型是否是列表。这就是我尝试的但是我遇到了错误。
let checkType (result : RopResult<'tSuccess, 'errors>) =
match result with
| Success (s, msg) ->
match s with
| :? [] -> // error here
样品
let isList<'s> () = true
let processList (ls : 'domain list) = true
let processType (s : 'domain) = true
let checkType (result : RopResult<'tSuccess, 'errors>) =
match result with
| Success (s, msg) ->
match s with
| s when isList<s>() -> processList s
| _ -> processType s
| Failure (x) -> false
答案 0 :(得分:2)
我不确定我是否真的理解你的问题
一般来说,如果你有一些多态类型(比如你的([\s\S]*?)
)并且想要处理它的多态部分,那么F#中的一个好方法就是
将代码解压缩为包装代码和处理器代码,处理器代码通过处理器部件的高阶函数传递。
示例:
RopResult
和
type RopResult<'tSuccess, 'tError> =
| Success of 'tSuccess
| Error of 'tError
let checkType (process: 'tSuccess -> 'tResult) (result : RopResult<'tSuccess, 'tError>) =
match result with
| Success s -> process s |> Success
| Error e -> Error e
然后你
let processList (ls : 'domain list) = true
let processType (s : 'domain) = true
答案 1 :(得分:2)
假设您想确定提供的值是否属于通用列表类型,您可以这样做:
let isList value =
let valueType = value.GetType()
match valueType.IsGenericType with
|true -> valueType.GetGenericTypeDefinition() = typedefof<_ list>
|false -> false
使用示例:
isList [5];; val it : bool = true isList ["a", "b"];; val it : bool = true isList "a";; val it : bool = false
使用RopResult
或更正式的Either
之类的内容时,定义map
函数会很有帮助。 map
函数采用函数'a -> 'b
,并为您提供在某个高架域中运行的函数,例如RopResult<'a,'c> -> RopResult<'b,'c>
。
这类似于List.map : ('a ->'b) -> 'a List -> 'b List
。
我们这样定义:
let map f v =
match v with
|Success sv -> Success (f sv)
|Failure fv -> Failure (fv)
然后您可以在isList
上使用RopResult
,只需执行以下操作:
ropResult |> map isList
其他人在评论中警告您,一旦确定类型是否为列表,可能存在关于如何实际处理结果的潜在问题。具体而言,您需要确保processList
和processType
函数的返回类型相同(尽管我建议您重新访问processType
的命名并将其命名为processValue
因为你没有按类型操作,我认为这个名字令人困惑。)
答案 2 :(得分:2)
我将首先解释如何使代码工作的技术细节,然后尝试说服您(与此线程中的其他人一样)可能不是解决问题的正确方法。
首先,您的匹配语句有语法错误。你可以写一下类型测试和演员阵容
match s with
| :? List<int> as theIntList -> ...do something with theIntList ...
当您将其添加到代码中时,F#编译器会抱怨“运行时强制或类型测试...涉及不确定类型....需要进一步的类型注释”。通过更具体地说明您的checkType
处理的结果类型来解决这个问题:它是一些System.Object
实例和消息,所以你要写:
let checkType (result : Result<obj*string, 'errors>) =
match result with
| Success (s, msg) ->
match s with
| :? List<int> as theIntList -> ... do something
请注意,您无法将其更改为List<_>
这样的通用内容 - F#将一次性执行类型测试和投射,因此不会知道要投射什么至。如果您尝试,则会看到警告:List<_>
已被推断为List<obj>
说了这么多:使用obj
并不是惯用的方式,正如其他人已经试图指出的那样。 @robkuz和@TheInnerLight的答案包含您所需要的一切:map
函数,对各个结果类型进行操作的函数,然后可以很好地组合:
let map f x =
match x with
| Success (s, msg) -> Success (f s, msg)
| Failure f -> Failure f
// This will automatically be inferred to be of type Result<(int list * string), 'a>
let myFirstResult = Success ([1;2], "I've created an int list")
// This will automatically be inferred to be of type Result<(string list * string), 'a>
let mySecondResult = Success (["foo"; "bar"], "Here's a string list")
// Process functions for specific result types. No type tests needed!
let processIntList (l: int list) = Seq.sum l
let processStringList = String.concat "; "
// This will automatically be inferred to be of type Result<(int * string), 'a>
let mapFirst = myFirstResult |> map processIntList
// This will automatically be inferred to be of type Result<(string * string), 'a>
let mapSecond = mySecondResult |> map processStringList