Functional programming 是否可能通过DCG在Prolog中使用镜头?

Functional programming 是否可能通过DCG在Prolog中使用镜头?,functional-programming,prolog,composition,dcg,lenses,Functional Programming,Prolog,Composition,Dcg,Lenses,在序言里玩镜头。透镜是一种显微镜,可以放大结构,并以功能性方式进行读写操作。基本上,我的出发点是在Prolog中对setter和声明getter进行以下建模: Getter:只是一个, 被称为调用(,X,Y), 这将从X中检索值Y 声明性Setter:相同的,但使用不同的arity, 称为call(,X,Y,Z),这将通过一个新值Y更新X,给出一个新的Z 我很快就得出了镜头合成操作符的定义,它可以根据两个镜头的闭包将两个镜头组合成一个新镜头。附录中给出了一个示例和定义。但是根据这个原理,透镜可以

在序言里玩镜头。透镜是一种显微镜,可以放大结构,并以功能性方式进行读写操作。基本上,我的出发点是在Prolog中对setter和声明getter进行以下建模:

Getter:只是一个

被称为
调用(,X,Y)
, 这将从
X
中检索值
Y

声明性Setter:相同的
,但使用不同的arity,
称为
call(,X,Y,Z)
,这将通过一个新值
Y
更新
X
,给出一个新的
Z

我很快就得出了镜头合成操作符的定义,它可以根据两个镜头的闭包将两个镜头组合成一个新镜头。附录中给出了一个示例和定义。但是根据这个原理,透镜可以简单地合成

在我看来,当某个东西是组合的时,它可以通过DCG很容易地建模。我可以按如下方式为getter执行此操作,但我还没有找到为声明性setter执行此操作的方法:

/* Getter composition as DCG */
@(C1, C2) --> 
     call(C1),
     call(C2).
我将如何在DCG中为setter组合建模?这是可能的,可能会改变getter和声明性setter建模的初始假设,从而使结果只是合成的吗

致意

附件: 下面是一些setter和getter的示例:

/* getter */
back(bicycle(X, _), X).
front(bicycle(_, Y), Y).
circumference(wheel(X, _), X).
spokes(wheel(_, Y), Y).

/* setter */
back(bicycle(_, Y), X, bicycle(X, Y)).
front(bicycle(X, _), Y, bicycle(X, Y)).
circumference(wheel(_, Y), X, wheel(X, Y)).
spokes(wheel(X, _), Y, wheel(X, Y)).
以下是镜头组成的建模:

:- op(600, xfy, @).

/* getter composition */
@(C1, C2, X, Y) :-
    call(C1, X, H),
    call(C2, H, Y).

/* setter composition */
@(C1, C2, X, Y, Z) :-
    call(C1, X, H),
    call(C2, H, Y, J),
    call(C1, X, J, Z).
以下是一些运行示例:

Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.3.16)
Copyright (c) 1990-2015 University of Amsterdam, VU Amsterdam

?- call(front@spokes, bicycle(wheel(1330, 12), wheel(1440, 16)), X).
X = 16.

6 ?- call(back@circumference, bicycle(wheel(1330, 12), wheel(1440, 16)), X).
X = 1330.

7 ?- call(front@circumference, bicycle(wheel(1330, 12), wheel(1440, 16)), 1420, X).
X = bicycle(wheel(1330, 12), wheel(1420, 16)).
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.3.14-1-ga20f192)
Copyright (c) 1990-2015 University of Amsterdam, VU Amsterdam

?- ['lens.pro'].

?- call(front@spokes, id, F), call(F, bicycle(wheel(1330, 12), wheel(1440, 16)), X).
F = front(spokes(id)),
X = 16.

?- call(back@circumference, id, F), call(F, bicycle(wheel(1330, 12), wheel(1440, 16)), X).
F = back(circumference(id)),
X = 1330.

?- call(front@circumference, id, F), call(F, bicycle(wheel(1330, 12), wheel(1440, 16)), 1420, X).
F = front(circumference(id)),
X = bicycle(wheel(1330, 12), wheel(1420, 16)).

有一种解决方案具有进一步的间接性,但也有可能以某种方式预编译访问路径。我们再次将访问路径视为闭包,但这次它们修改了延续函数。有两种类型的延续:

Getter Continuation:
-在返回值之前转换该值。
声明性Setter延续:
-在更新值之前,通过附加参数转换该值

现在,access path元素将转换这两个延续,以提供新的延续。访问路径元素转换是组合的,因此首先应用内部访问元素

附录中给出了一些示例延续,我们可以通过DCG对访问元素的组成进行建模,如下所示。注意DCG主体中的顺序,这反映了前面提到的访问元素顺序

/* composition */
@(C1, C2) :-
   call(C2),
   call(C1).
再见

附件: 以下是一些转换器定义:

/* transformer construction */
back(F, back(F)).
front(F, front(F)).
circumference(F, circumference(F)).
spokes(F, spokes(F)).

/* getter transformer */
back(F, bicycle(X, _), Y) :- call(F,X,Y).
front(F, bicycle(_, X), Y) :- call(F,X,Y).
circumference(F, wheel(X, _), Y) :- call(F,X,Y).
spokes(F, wheel(_, X), Y) :- call(F,X,Y).

/* setter transformer */
back(F, bicycle(X, Y), Z, bicycle(T, Y)) :- call(F,X,Z,T).
front(F, bicycle(X, Y), Z, bicycle(X, T)) :- call(F,Y,Z,T).
circumference(F, wheel(X, Y), Z, wheel(T, Y)) :- call(F,X,Z,T).
spokes(F, wheel(X, Y), Z, wheel(X, T)) :- call(F,Y,Z,T).
以下是镜头组成和一些停止变压器:

:- op(600, xfy, @).

/* composition */
@(C1, C2, F, G) :-
   call(C2, F, H),
   call(C1, H, G).

/* stop getter */
id(X,X).

/* stop setter */
id(_,X,X).
以下是一些运行示例:

Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.3.16)
Copyright (c) 1990-2015 University of Amsterdam, VU Amsterdam

?- call(front@spokes, bicycle(wheel(1330, 12), wheel(1440, 16)), X).
X = 16.

6 ?- call(back@circumference, bicycle(wheel(1330, 12), wheel(1440, 16)), X).
X = 1330.

7 ?- call(front@circumference, bicycle(wheel(1330, 12), wheel(1440, 16)), 1420, X).
X = bicycle(wheel(1330, 12), wheel(1420, 16)).
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.3.14-1-ga20f192)
Copyright (c) 1990-2015 University of Amsterdam, VU Amsterdam

?- ['lens.pro'].

?- call(front@spokes, id, F), call(F, bicycle(wheel(1330, 12), wheel(1440, 16)), X).
F = front(spokes(id)),
X = 16.

?- call(back@circumference, id, F), call(F, bicycle(wheel(1330, 12), wheel(1440, 16)), X).
F = back(circumference(id)),
X = 1330.

?- call(front@circumference, id, F), call(F, bicycle(wheel(1330, 12), wheel(1440, 16)), 1420, X).
F = front(circumference(id)),
X = bicycle(wheel(1330, 12), wheel(1420, 16)).

哇,是的,标签镜头太多了!