我正在编码 在 OCaml 的 van Laarhoven 镜头的一种形式,但由于价值限制,我有困难。
有关守则如下:
module Optic : sig
type (-'s, +'t, +'a, -'b) t
val lens : ('s -> 'a) -> ('s -> 'b -> 't) -> ('s, 't, 'a, 'b) t
val _1 : ('a * 'x, 'b * 'x, 'a, 'b) t
end = struct
type (-'s, +'t, +'a, -'b) t =
{ op : 'r . ('a -> ('b -> 'r) -> 'r) -> ('s -> ('t -> 'r) -> 'r) }
let lens get set =
let op cont this read = cont (get this) (fun b -> read (set this b))
in { op }
let _1 = let build (_, b) a = (a, b) in lens fst build
end
在这里,我代表一个透镜作为一个高阶类型,一个变压器的 CPS 转换函数 ('a -> 'b) -> ('s -> 't)
(正如建议 给你和讨论 给你)。函数 lens
、 fst
和 build
都有完全广义的类型,但是它们的组成 lens fst build
没有。
Error: Signature mismatch:
...
Values do not match:
val _1 : ('_a * '_b, '_c * '_b, '_a, '_c) t
is not included in
val _1 : ('a * 'x, 'b * 'x, 'a, 'b) t
如大意所示,完全可以编写 _1
let _1 = { op = fun cont (a, x) read -> cont a (fun b -> read (b, x)) }
但是,每次都必须手工构建这些镜头是非常繁琐的,如果使用高阶函数(如 lens
)来构建它们就更好了。
有什么办法可以绕过这个价值限制吗?