鉴于DU喜欢
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$(window).on('scroll', function(){
$('ul li').removeClass("active");
$('ul li').addClass("deactive");
});
});
</script>
<style>
.active{
color:red;
}
.deactive{
color:green;
}
</style>
</head>
<body style="height:9500px;">
<ul>
<li class="active">a</li>
<li class="active">a</li>
<li class="active">a</li>
<li class="active">a</li>
<li class="active">a</li>
<li class="active">a</li>
<li class="active">a</li>
<li class="active">a</li>
<li class="active">a</li>
<li class="active">a</li>
<li class="active">a</li>
<li class="active">a</li>
</ul>
</body>
</html>
和一些功能
type Result<'a, 'b> = Ok of 'a | Error of 'b
如何定义一个函数来转换值?
let doA () = Ok true
let doB () = Error <| exn "Fail"
let doC = function | 1 -> Ok "one" | x -> Error x
用法
toObjResult : x:obj -> Result<obj, obj> //where x is guaranteed to be Result<'a,'b>
到目前为止,所有尝试都将let data =
[ doA() |> box
doB() |> box
docC 1 |> box
docC 2 |> box ]
|> List.map toObjResult
和'a
的类型限制为'b
obj
导致错误,如
let toObjResult (x:obj) =
match x with
| :? Result<'a, 'b> as r ->
match r with
| Ok a -> Ok (box a)
| Error b -> Error (box b)
| _ -> Error <| (exn "Invalid type" |> box)
答案 0 :(得分:4)
您必须在匹配表达式
中匹配Result类型的确切泛型类型参数let matchR r =
match r with
| Ok a -> Ok (box a)
| Error b -> Error (box b)
let toObjResult (x:obj) =
match x with
| :? Result<bool, _> as r -> matchR r
| :? Result<string, int> as r -> matchR r
| :? Result<_, Exception> as r -> matchR r
| _ -> Error (box "Invalid type" )
遗憾的是,你无法匹配未实现的类型参数(这真的很糟糕)
答案 1 :(得分:4)
如果不使用反射,枚举所有类型或修改类型,则无法执行此操作。
使用反射可能很慢,但可以让你做你想做的事情(参见[GenericType
活动模式from this answer),@ robkuz的答案显示了如何通过列出所有案例来做到这一点你想要涵盖的 - 问题是这不能很好地扩展。
最后,如果您乐意修改Result<'a, 'b>
类型,则可以添加一个非通用接口,以便将值作为盒装值获取:
type IBoxedResult =
abstract Boxed : Result<obj, obj>
and Result<'a, 'b> =
| Ok of 'a
| Error of 'b
interface IBoxedResult with
member x.Boxed =
match x with
| Ok v -> Ok (box v)
| Error v -> Error (box v)
现在,您可以将obj
投射到IBoxedResult
并使用Boxed
将值设为Reslt<obj, obj>
:
[ box (Ok true)
box (Ok 1) ]
|> List.map (fun o -> (o :?> IBoxedResult).Boxed)