我正在编写van Laarhoven透镜的一种OCaml编码,但由于值限制而遇到了困难。
相关代码如下:
我在这里将镜头表示为一种高阶类型,即 CPS 转换函数的转换器
正如所示的那样,在这个代码片段中,编写
相关代码如下:
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
)构建它们会更好。
是否有任何方法可以避免这里的值限制?