Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/wcf/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Types 阴阳连续体之谜在打字语言中有意义吗?_Types_Functional Programming_Scheme_Continuations - Fatal编程技术网

Types 阴阳连续体之谜在打字语言中有意义吗?

Types 阴阳连续体之谜在打字语言中有意义吗?,types,functional-programming,scheme,continuations,Types,Functional Programming,Scheme,Continuations,这个问题涉及到。方案中延续的阴阳示例如下所示: 我试图用一种(编辑:静态)类型的语言(如SML/NJ)编写一段等效的代码,但它给了我输入错误。因此,要么拼图无法输入,要么我误解了scheme语法。上述代码在SML或Ocaml中是什么样子的(带有callcc扩展名) 顺便问一下,谜题的来源是什么?它是从哪里来的 编辑:我想我知道答案。对于某些类型s,我们需要一个递归类型t满足t=t->s 编辑编辑:不是,答案是递归类型t满足t=t->t另请参见我的答案,在回答这个问题之前,我必须找出答案 作为一种

这个问题涉及到。方案中延续的阴阳示例如下所示:

我试图用一种(编辑:静态)类型的语言(如SML/NJ)编写一段等效的代码,但它给了我输入错误。因此,要么拼图无法输入,要么我误解了scheme语法。上述代码在SML或Ocaml中是什么样子的(带有
callcc
扩展名)

顺便问一下,谜题的来源是什么?它是从哪里来的

编辑:我想我知道答案。对于某些类型
s
,我们需要一个递归类型
t
满足
t=t->s

编辑编辑:不是,答案是递归类型
t
满足
t=t->t

另请参见我的答案,在回答这个问题之前,我必须找出答案

作为一种“类型化”语言本身并不影响这个谜题是否可以在其中表达(无论“类型化语言”一词多么模糊)。然而,从字面上回答您的问题:是的,这是可能的,因为Scheme本身是一种类型化语言:每个值都有一个已知的类型。这显然不是你的意思,所以我假设你的意思是,在一种语言中,每个变量都被分配了一个永远不会改变的永久类型(也称为“静态类型语言”),这是否可能

此外,我假设您希望在用某种语言表达时保留拼图的精神。显然,可以用x86机器代码编写Scheme解释器,也可以用只有整数数据类型和函数指针的类型化语言编写x86机器代码解释器。但结果却不尽相同。因此,为了使这一点更加精确,我将提出一个额外的要求:结果必须使用真正的连续性来表示。不是模仿,而是真正的完全延续

那么,你能不能有一种带有continuations的静态类型语言?事实证明你可以,但你仍然可以称之为作弊。例如,在C#中,如果我的continuations被定义为“接受一个对象并返回一个对象的函数”,其中“object”是一种可以容纳任何东西的类型,您会接受吗?如果函数接受并返回一个“动态”怎么办?如果我有一种“类型化”语言,其中每个函数都有相同的静态类型:“函数”,而不定义参数类型和返回类型,该怎么办?即使使用了真正的延续,最终的程序是否仍然具有相同的精神

我的观点是,“静态类型”属性仍然允许类型系统中有大量的变化,足以产生所有的差异。因此,为了好玩,让我们考虑类型系统需要支持什么,以便以任何措施限定为非作弊。

操作员
call/cc(x)
也可以写成
x(get/cc)
,在我看来这更容易理解。这里,
x
是一个函数,它接受一个Continuation并返回一个值,而
get/cc
返回一个
Continuation
<代码>延续具有函数的所有特性;它可以用一个参数调用,并将在某种程度上替换传递到创建它的get/cc最初所在的位置的值,另外在该位置继续执行

这意味着get/cc有一个笨拙的类型:它是一个
函数
,但同一个位置最终将返回一个我们还不知道其类型的值。但是,假设按照静态类型语言的精神,我们要求返回类型是固定的。也就是说,调用continuation对象时,只能传入预定义类型的值。使用这种方法,可以使用形式为
T=function T->T
的递归表达式定义连续函数的类型。正如一位朋友所指出的,这种类型实际上可以在C#中声明:
公共委托T(T)

所以你有它;“类型化”并不排除也不保证您可以在不改变其性质的情况下表达此谜题。然而,如果您允许静态类型“可以是任何东西”(在Java和C#中称为
object
),那么您唯一需要的就是支持真正的延续,并且可以毫无问题地表示这个谜题


从一个不同的角度来看同样的问题,考虑我把这个谜改写为一个更让人联想到传统的静态类型命令式语言的东西,我在下面的解释中是这样解释的:

yin=(函数(arg){print@;返回arg;})(获取cc);
yang=(函数(arg){print*;return arg;})(get cc);
阴(阳);

在这里,阴和阳的类型永远不会改变。它们总是存储一个“取C并返回C的延续C”。这与静态类型非常兼容,静态类型的唯一要求是下次执行该代码时类型不会更改。

我想我将回答我自己的问题。我将展示两种解决方案,一种是eff,另一种是Ocaml

效率 我们将使用(我在这里吹响我自己的号角,请参阅下文了解OCaml中的另一种方法)

首先,我们在eff中定义
shift
reset

type ('a, 'b) delimited =
effect
  operation shift : (('a -> 'b) -> 'b) -> 'a
end

let rec reset d = handler
  | d#shift f k -> with reset d handle (f k) ;;
以下是转录成eff的阴阳拼图:

let y = new delimited in
  with reset y handle
    let yin = (fun k -> std#write "@" ; k) (y#shift (fun k -> k k)) in
    let yang = (fun k -> std#write "*" ; k) (y#shift (fun k -> k k)) in
      yin yang
但是eff抱怨说它不能解类型方程 α = α → β. 目前eff无法处理任意递归类型,因此我们陷入了困境。作为一种作弊方式,我们可以关闭类型检查,看看代码是否至少达到了预期的效果:

$ eff --no-types -l yinyang.eff
@*@**@***@****@*****@******@*******@********@*********@*******...
好的,它做的是正确的,但是类型不够强大

奥卡姆 对于这个例子,我们需要。代码如下
$ eff --no-types -l yinyang.eff
@*@**@***@****@*****@******@*******@********@*********@*******...
open Delimcc ;;

let y = new_prompt () in
  push_prompt y (fun () ->
    let yin = (fun k -> print_string "@" ; k) (shift y (fun k -> k k)) in
    let yang = (fun k -> print_string "*" ; k) (shift y (fun k -> k k)) in
      yin yang)
ocamlc -rectypes -o yinyang delimcc.cma yinyang.ml
$ ./yinyang
@*@**@***@****@*****@******@*******@********@*********@...