go
在阅读Haskell的材料或资料时,我会看到很多东西,但是我从未真正感到满意-(我想它在我的脑海中具有“ goto”的负面含义)。我开始学习Haskell与LYAH,而且在那里我拿起使用倾向的acc
和step
当写倍。书写惯例go
从何而来?
最重要的是,这个名字到底go
意味着什么?
go
在阅读Haskell的材料或资料时,我会看到很多东西,但是我从未真正感到满意-(我想它在我的脑海中具有“ goto”的负面含义)。我开始学习Haskell与LYAH,而且在那里我拿起使用倾向的acc
和step
当写倍。书写惯例go
从何而来?
最重要的是,这个名字到底go
意味着什么?
go
我读过的任何Haskell资料都从未见过。你能举个例子/参考吗?
Answers:
嗯!一些考古!
从2004年左右开始go
,当对递归函数进行worker / wrapper转换时,我一直将其用作尾递归worker循环的通用名称。我开始在中广泛使用它bytestring
,例如
foldr :: (Word8 -> a -> a) -> a -> ByteString -> a
foldr k v (PS x s l) = inlinePerformIO $ withForeignPtr x $ \ptr ->
go v (ptr `plusPtr` (s+l-1)) (ptr `plusPtr` (s-1))
where
STRICT3(go)
go z p q | p == q = return z
| otherwise = do c <- peek p
go (c `k` z) (p `plusPtr` (-1)) q -- tail recursive
{-# INLINE foldr #-}
是从bytestring
2005年8月开始的。
这是用RWH编写的,并且可能从那里开始流行。另外,在流融合库中,我和Duncan Coutts开始做很多事情。
来自GHC来源
这个习语可以追溯到更远。foldr
在GHC.Base中给出为:
foldr k z = go
where
go [] = z
go (y:ys) = y `k` go ys
这可能是我找到窍门的地方(我以为这是来自安迪·吉尔(Andy Gill)的论文,但在go
那里找不到任何用处)。它在Gofer中没有以这种形式给出,所以我认为这首先出现在GHC代码库中。
到2001年,Simon Marlowgo
在某些系统级代码中使用了,所以我们可能会将责任归咎于GHC,而这一线索使我们找到了GHC源代码,该源代码go
广泛用于工作者函数:
myCollectBinders expr
= go [] expr
where
go bs (Lam b e) = go (b:bs) e
go bs e@(Note (SCC _) _) = (reverse bs, e)
go bs (Cast e _) = go bs e
go bs (Note _ e) = go bs e
go bs e = (reverse bs, e)
GHC 3.02和格拉斯哥
挖掘GHC的旧版本,我们看到在GHC 0.29中没有出现这个成语,但是在GHC 3.02系列(1998年)中,这个go
成语随处可见。例如,在Numeric.lhs
的定义中showInt
,日期为1996-1997:
showInt n r
| n < 0 = error "Numeric.showInt: can't show negative numbers"
| otherwise = go n r
where
go n r =
case quotRem n 10 of { (n', d) ->
case chr (ord_0 + fromIntegral d) of { C# c# -> -- stricter than necessary
let
r' = C# c# : r
in
if n' == 0 then r' else go n' r'
}}
这与H98报告中给出的实现不同。深入研究“ Numeric.lhs”的实现,我们发现它与1997年添加到GHC 2.06的版本不同,1998年4月,Sigbjorne Finne出现了一个非常有趣的补丁,添加了一个go
循环到Numeric.lhs。
这表示至少到1998年,Sigbjorne才向go
GHC“ std”库中添加了循环,而同时,GHC编译器内核中的许多模块都有go
循环。进一步挖掘,Will Partain于1996年7月提交的这一非常有趣的内容为GHC添加了一个“ go”循环-该代码来自Simon PJ!
因此,我将其称为格拉斯哥成语,由格拉斯哥的人在90年代中期从事GHC工作时发明,例如Simon Marlow,Sigbjorn Finne,Will Partain和Simon Peyton Jones。
f
,我个人通常会使用f'
此类名称作为名称,尽管go
我可能会尝试使用某种近似关键字的习惯用法。有趣的是,showInt
使用惯用法避免多次评估同一个后卫。
goto
,并将控制权移交给了辅助函数。
loop
除非我要修改已经使用go
约定的代码。我一直以为它的字面意思是“走”,就像“绕圈走”。
显然唐的答案是正确的。让我仅添加一个小细节(因为您直接引用的似乎是我的著作):go很不错,因为它只有两个字母。
噢,Yesod的书为枚举程序包投入了如此多的内容的原因是,因为我已经将枚举程序的教程分为三部分,作为博客文章系列,所以决定我也应该将其包含在书中。在Yesod的许多地方都使用了枚举程序包,因此它是相关的。
我希望这个习惯用法不仅适用于线性结构(因此也适用于“循环”),也适用于分支(树状)结构。
我想知道go
模式多久对应一次累积参数,更普遍地说,是与Mitch Wand在论文《基于持续的程序转换策略》(我最喜欢的论文之一)中探讨的连续编码策略相对应的。在这些情况下,go
函数具有特殊含义,然后可以使用该含义从优雅的规范中得出有效的代码。
add_x
或consOnto_xs
。
loop
改为调用我的函数。