newtype a - &> b = hyp {Invoke ::(b - &> a) - > B}
这是一个高功能障碍(Launchury,Krstic和Sauerwein 2013; 2000; 2000),我认为这是你可以在Haskell写的最奇怪和最有趣的纽约人之一。
首先要注意的是递归模式很奇怪。对于一个类型来递归地在函数箭头的左侧递归,非常不寻常,但在递归的顶部是非常规的。这意味着递归参考对其父母的类型不同:A - &> b位于等号的左侧,但在右侧我们指的是b - >>一种。
奇怪是足以写下它们的原因,但是对超功能真正令人震惊的是它们是有用的。一旦我看到这个定义,我意识到我写的一堆优化代码(特别是熔断器,特别是熔断器)实际上是使用超程(Ghani等,2005)。之后,我看到他们到处都是:在科罗琳实现,队列,宽度第一遍历等。
无论如何,几个月前贯穿过期功能,我以为我会对他们进行撰写。我有点惊讶他们并不是众所周知,说实话:他们就像一个稍微更加致力于更酷的名字。让我们进入它!
Newtype噪声的含量覆盖了超速功能的内容:扩展定义可能会使事情稍微更清晰。
类型A - &> B =(B - & a) - > B =((A - &> b) - > a) - > B =(((b - & a) - > b) - > a) - > B =(((... - > b) - > a) - > b) - > a) - > B.
所以A型 - &> b是无限左嵌套的功能类型。值得注意的一件事是所有的原样都是负面位置和所有BS的正面。这个负面和积极的业务基本上是指与函数箭头相关的参数的位置:左边是否定,右边是积极的,但两个负面取消了两个否定。
((((... - > b) - > a) - > b) - > a) - > B + - + - +
消极位置的所有事情都是像功能“消耗”的东西,而积极的位置是“产生的”。非常值得摆弄非常嵌套的函数类型,以为这个概念感受到这一概念。然而,对于超功能,它足以知道a - > B确实(种类)占据了一堆,它有点生产BS。
顺便说一下,在这个意义上掌握极性的方法之一是与Cont Monad,Codenty Monad或Selection Monad(Hedges 2015)一起游戏。如果您这样做,您可能会注意到关于超功能的有趣相似之处:A型 - &> a实际上是延续的Monad的固定点(FIX(续))。可疑的!
在进一步进入类型本身的属性之前,我想提供一些在漂亮的标准优化代码中出现的示例。
假设您想要用FOLDR编写ZIP(我已经在上一个帖子中描述了这种特定的算法)。不是左侧论点的折扣,介意你,但两者都在折叠。如果您在机械上进行了操作,请用折扣替换每个递归函数,您实际上可以到达定义:
拉链:: [a] - > [b] - > [(a,b)] zip xs ys = foldr xf xb xs(foldr yf yb ys)其中xf x xkyk = yk x xk xb _ = [] Yf Y YK X XK =(x,y):xk yk yb _ _ = []
用没有递送的语言或具有递归类型的语言,这样的定义会完全没问题。但是,在Haskell,编译器将抱怨以下内容:
•发生检查:无法构建无限类型:t0〜a - > (t0 - > [(a,b)]) - > [(a,b)]
然而,经验丰富的Haskellers将知道,这不是类型错误:否,这是一个类型的配方。编译器正在告诉你它希望您在纽特氏键中粘在纽特的参数:
Newtype zip a b = zip {runzip :: a - > (Zip A B - > [(a,b)]) - > [(a,b)]} zip :: forall a b。 [a] - > [b] - > [(a,b)] zip xs ys = xz yz,其中xz :: zip a b-> [(a,b)] xz = foldr fb xs其中fx xk yk = runzip yk x x xk b _ = [] YZ :: ZIP AB YZ = FY YK = ZIP(\ x XK - >(x ,Y):XK YK)B = ZIP(\ _ _ - > [])
在这里,我们看到了难以捉摸的高功能:隐藏在略微变化的参数订单后,ZIP A B实际上与[(a,b)]相同。>> (a - > [(a,b)])。
zip :: forall a b。 [a] - > [b] - > [(a,b)] zip xs ys =调用xz yz,其中xz ::(a - > [(a,b)]) - > [(a,b)] xz = foldr fb xs其中fx xk = hyp(\ yk - >调用yk xk x)b = hyp(\ _-> [])yz :: [(a,b)] - &> (a - > [(a,b)])yz = fy yk = hyp(\ xk x - >(x,y):调用xkyk)b = hyp(\ _ _ - > [])
在另一个前一篇文章中,我派生了以下函数来做一棵树的宽度第一遍历:
数据树A = A:& [树A]纽特本q a = q {q ::(q a - > [a]) - > [a]} bfe ::树a - > [a] bfe t = q(f t b)e其中f ::树a - > q a - > q af(x:& xs)fw = q(\ bw - > x:q fw(bw。翻转(flipr f)xs))b :: q ab = q(\ k - > kb)e: :q a - > [a] e(q q)= q e
BFE ::树A - > [a] bfe t =调用(f t e)e,其中f ::树a - > ([a] - & [a]) - > ([a] - &> [a])f(x:& xs)fw = hyp(\ bw - > x:调用fw(hypoke bw。翻转(foldr f)xs))e :: [a] - > [a] e = hyp(\ k - >调用k e)
我拥有上述功能的问题之一是它没有终止:它可以枚举树的所有元素,但它不知道何时停止。类似的计划(Allison 2006;描述并翻译成斯米什2009年的Haskell)管理以解决柜台的问题。它会震惊你找出这个解决方案也可以用高函数编码吗?
bfe t =调用(f t e)e 1其中f ::树a - > (int - > [a]) - > (int - > [a]) - > (int - > [a]) - > (int - > [a])f(x:& xs)fw = hyp(\ bw n - > x:调用fw(hypoke bw。翻转(foldr f)xs)(n + 1) )e ::(int - > [a]) - &> (int - > [a])e = hyp b b x 0 = [] b x n =调用x(hyp b)(n - 1)
(这里的版本实际上是一个与史密斯2009中的一个不同的位,但基本的想法是相同的)
似乎对我来说似乎与金融有关。在Coroutine实现中的至少几种类型中是实际的超功能。 Pieters和Schrijvers(2019)的Prodpar和Conspart类型是好的例子:
newtype prodpar a b = prodpar(conspar a b - > b)newtype conspar a b = conspar(a - > prodpar a b - > b)
prodpar a b是(a - > b) - &> B,并将B到B-> (a - > b),通过以下职能见证:
fromp :: prodpar a b - > (a - > b) - &> b fromp(prodpar x)= hyp(x。toc)toc :: b - &> (a - > b) - >耦合A B TOC(HYPH H)=循环PARPAPR(\ x P - > H(FROP P)x)TOP ::(a - > b) - &> B - > prodpar一个b顶部(hyp x)= prodpar(x。fromc)fromc :: conspar a b - > B - &> (a - > b)fromc(截止p)= hyp(\ h x - > p x(top h))
事实上,这揭示了ZIP函数中发生的事情:我们将左侧列表转换为prodpar(制作人),以及向消费者右手,彼此应用。
除了直观的奇怪,在理论上是奇怪的。例如,在理论上,例如,您无法形成-&> B:如果您尝试过,您将遇到那些讨厌的大小限制,这阻止了我们从“所有集合集”中的东西。然而,Haskell类型没有设置,正是因为我们可以定义像A - &gt这样的东西。湾
出于略有不同的原因,对集合理论限制,我们无法定义AGDA中的超功能类型。以下将出现错误:
记录_↬_(a:type a)(b:b):键入(aℓ⊔b),其中归纳;构造函数下域中调用:(B↬A)→B
并且有充分的理由! AGDA不允许递归呼叫处于负面位置的递归类型。如果我们关掉阳性检查器,我们可以写咖喱的悖论(从这里取出的示例证明):
是的? :⊥↬⊥是的? .Invoke h = h .invoke h no! :(⊥↬⊥)→⊥否! h = h .invoke h繁荣:⊥繁荣=否!是的?
请注意,这不是终止检查器的问题:上面的示例在没有问题的情况下通过所有正常终端条件(即使↬被标记为配音)。这是直接的,因为类型本身不是积极的。
有趣的是,存在略有不同,几乎等同,过度函数的定义,不允许我们编写上述证明:
记录_↬_(a:type a)(b:b):键入(aℓ⊔b),其中归纳;构造函数下域中调用:((a≠b)→a)→b
这基本上是一个略微扩展的超功能类型,重要的是,重要的是它是积极的。然而,由于递归呼叫确实发生在函数箭头的左侧:它是正数的左边的左边的左边的功能箭头的左侧。
我在Sjöberg(2015)中发现了一些关于这种额外严格问题的有趣讨论的一些有趣的讨论:在COQ,允许某些积极但不是严格的类型,确实引入了不一致的(烤架和保寿1990)。然而,这种不一致依赖于agda没有的Impriticative宇宙。据我所知,允许在Agda(Coquand 2013)中允许上面的类型(CONQUANDS 2013)可能是安全的,尽管我并不确定所有AGDA的较新功能仍然如此。
之前已经注意到非严格肯定类型和广度遍历之间的联系:Berger,Matthes和Setzer(2019)使用Hofmann(1993)的广度第一遍历算法在AGDA和COQ中纳入AGDA和CO。 ,使用以下类型:
现在这种类型不是高障碍(但它关闭);我们很快就会看到它是什么样的东西。
所以我们已经看到,通过一定的优化,我们看到的异常出现了一句,我们已经看到他们在理论上解释方面占据了一个奇怪的空间:我们尚未在孤立中看到类型本身。幸运的九百威特已经编写了超额障碍套餐(2015),其中提供了一种洗衣出席的实例列表,这可以告诉我们一些关于超额功能实际上可以自己做的事情的更多信息。
实例类别( - &>)其中Id = hyp(\ k - >调用k id)f。 g = hyp(\ k - >调用f(g。k))
我们实际上已经看到了几次的身份函数:我们将其用作广度 - 第一遍历算法中递归的基本情况。
我们实际使用的构成也使用,但它更模糊。一个类比帮助清楚的事情,是将超功能视为一种堆栈。 ID是空堆栈,我们可以使用以下功能将项目推送到堆栈上:
推送::(A - > b) - > a - &> B - > a - &> b按f q = hyp(\ k - > f(调用k q))
从这个意义上了解,组成类似于堆叠的拉链操作,因为我们有以下法律:
推动f p。推动g q≡推(f。g)(p。q)
虽然我们无法直接从堆栈的顶部真正弹出元素,但我们可以接近调用,因为它满足以下法律:
除了我们拥有的ID实现之外,这将让我们运行超功能,基本上折叠堆栈的内容:
这一类比帮助我们了解宽度的遍历如何工作:多功能是与𝒪(1)\ Mathcal {O}(1)推和拉链的堆栈,这恰恰是您需要的高效广度遍历。
BFE ::树A - > [a] bfe =运行。 f(x:& xs)= push(x :)(拉链(map f xs))拉链= foldr(。)id
实例Monad(( - &>)a)其中m>> = f = hyp(\ k - >调用(f(调用m(vervoke k。(>> = f))) ))k)
我不会假装了解这里发生了什么,但它看起来有点像一个嵌套读者蒙伙伴。也许有一些直觉从注意到一个 - >> 〜修复(续a)。
正如我在介绍中所说,我有点惊讶,在超速禁运中没有更多的研究。除了由Launchury,Krstic和Sauerwein(2013)的优秀论文除外,那里没有太多。也许这对他们来说并不是那么多理论深度,但是所有相同的问题都有一些值得注意的问题。
例如:是否有一个超级功能变压器?或者,失败了,你可以在任何时候穿过类型的单一,你有什么兴趣吗?
我在这个问题上发了一点,同时摆弄了上面的BFE定义之一。基本上我想删除终止BFE的INT计数器,我想使用一个可能的某处。我最终从可能到任何m概念,产生以下类型:
newtype hypm m a b = hypm {Invokem :: m((hypm m a b - > a) - > b)}
bfe t = r(f t e)其中f ::树a - > Hypm可能[a] [a] - > Hypm可能[a] [a] f(x:& xs)fw = hypm(只是(\ bw - > x:frommaybe(\ k - > ke)(incokem fw)(bw。翻转(flowr f) xs)))e :: hypm可能[a] [a] e = hypm nother r :: hypm可能[a] [a] - > [a] r =可能[](\ k - > k r)。 Invokem.
(实际上,当M是专门的,也许我们有与Rou相同的类型)
这种类型具有非常实际的使用,因为它发生了,这与教堂编码列表Monad变压器有关:
newtype listt m a = listt {runlistt :: forall b。 (a - > m b - > m b) - > m b - > M B}
就像 - &>允许我们在折叠上写下zip(即,使用foldr),kepm将允许我们在listt上写zipm:
ZIPM :: Monad M => listt m a - > listt m b - > listt m(a,b)zipm xs ys = listt(\ cn - > let xf x xk =纯(\ yk - > yk(hypm xk)x)xb =纯度(\ _ - > n)yf y YK =纯(\ xk x - > c(x,y)(加入(invokem xk< * yk)))yb =加入中的纯(\ __ - > n)(RunListt XS XF XB&Lt ; *> runlistt ys yf yb)))
我实际上认为这个函数可以用来认真改进几个关于logict函数的运行时间:我对它们的读取表明,交错是𝒪(n 2)\ mathcal {o}(n ^ 2)(或更坏),但上面的zip可以术语重新估算,以给出𝒪(n)\ mathcal {o}(n)交织。这也将对例如,>> - 等等。 - 等等。
另一个问题是关于高障碍的箭头。我们已经看到,一个超级障碍的东西增加了“堆叠”的功能,可以对其他箭头做同样的事情吗?基本上,以下类型是否有用?
newtype hypp p a b = hypp {vipokep :: p(hypp p b a)b}
沿着类似的静脉,许多广度第一枚举算法似乎使用“超额功能对基因族骨髓”。基本上,它们都产生了[a] - &amp的类型的超功能; [a],并与我们如何使用差异列表使用它们非常类似。但我们知道,其他单面类别中有Cayley转变,例如在申请人的大型类别中:我们可以构建那些的“超功能”版本?
艾莉森,劳埃德。 2006年。“循环计划和自我参照结构。”软件:练习和经验19(2)(10月):99-109。 DOI:10.1002 / SPE.4380190202。 http://users.monash.edu/~lloyd/tildefp/1989spe/
Berger,Ulrich,Ralph Matthes和Anton Setzer。 2019年。“Martin Hofmann的非严格性数据类型的案例。”在第24届关于校样和计划类型(2018型)的国际会议中,由。 Peter Dybjer,JoséEspíritoSanto,以及LuísPinto,130:22。莱布尼斯信息学(脂质)的国际诉讼程序。 Dagstuhl,德国:Schloss Dagstuhlleibniz-Zentrum Fuer Informatik。 DOI:10.4230 / LIPICS.TYPES.2018.1。 http://drops.dagstuhl.de/opus/volltexte/2019/11405。
克栅,蒂埃里和克里斯汀·保尔林。 1990年。“禁用定义类型。”在Colog-88,Ed。每马丁-Löf和格里戈里薄荷糖,50-66。计算机科学的讲座。柏林,海德堡:斯普林克。 DOI:10.1007 / 3-540-52335-9_47。
Ghani,Neil,Patricia Johann,Tarmo Uustalu和Varmo Vene。 2005年。“Monadic增强和广义短切融合”。在第十届ACM履行委员会国际功能规划国际会议上,294-305的诉讼程序。 ICFP '05。纽约,纽约,美国:计算机械协会。 DOI:10.1145 / 1086365.1086403。 https://doi.org/10.1145/1086365.1086403。
树篱,朱尔斯。 “2015年。”选择单一作为CPS转型。“ arxiv:1503.06061 [CS](3月)。 http://arxiv.org/abs/1503.06061。
Launchurance,J.,S.Krstic和T.Sauerwein。 2013年。“具有超功能的金属折叠。”电子。 Proc。你。计算。 SCI。 129(9月):121-135。 DOI:10.4204 / EPTCS.129.9。 http://arxiv.org/abs/1309.5135。
Pieters,Ruben P.和Tom Schrijvers。 2019年。“较快的金融管道:重建。”在陈述语言的实践方面,ed。 JoséJúlioAlferes和Moa Johansson,133-149。计算机科学的讲座。 Cham:Springer国际出版社。 DOI:10.1007 / 978-3-030-05998-9_9。 https://people.cs.kuleuven.be/~tom.schrijvers/portfolio/padl2019.html。
Sjöberg,vilhelm。 “为什么必须严格积极的归纳类型?” 代码和东西。 https://vilhelms.github.io/posts/why-must-inductive-types-be-strictly-positive/。 史密斯,莱昂P. 2009.“Lloyd Allison的经纪队列:为什么持续存在。” Monad.Reader 14(14)(7月)(7月):28。https://meldingmonads.files.wordpress.com/2009/06/corecqueues.pdf。