1. ホーム
  2. haskell

[解決済み] Haskell: なぜヘルパー関数に "go" という名前を付けるのですか?

2023-02-12 21:52:32

質問

なるほど go は、Haskellの資料やソースを読んでいるとよく目にしますが、私はこれまであまり気にしたことがありませんでした(私の中では "goto" というネガティブな意味合いがあるようです)。私はLYAHでHaskellを学び始め、そこで accstep と書くことができます。を記述する規約はどこにあるのでしょうか? go はどこから来たのでしょうか?

最も重要なのは、具体的にどのような名前で go という名前は何を意味するのでしょうか?

どのように解決するのですか?

ん!?考古学か!

2004 年頃から、私は go を、再帰的な関数のワーカー/ラッパー変換を行う際の末尾再帰的なワーカーループの総称として使ってきました。これを広く使い始めたのは 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 Marlowは go を使用していたので、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とGlasgow

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 のループがある。さらに掘り下げると、この は 1996 年 7 月の Will Partain による非常に興味深いコミットで、GHC に "go" ループを追加しています。 -- コードはSimon PJのものです!

ということで、これを グラスゴーのイディオム のように、90年代半ばにGHCに携わっていたグラスゴーの人たちが発明したものです。 Simon Marlow , シグビョーン・フィンネ , ウィル・パーテイン および サイモン・ペイトン・ジョーンズ .