128

在 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)处所建议和所讨论)。函数,和都具有完全泛化的类型,但它们的组合没有。lensfstbuildlens 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.

有什么办法可以绕过这里的价值限制吗?

4

0 回答 0