Haskell: почему условно назвать вспомогательную функцию "go"?


Я вижу go много при чтении материала или источника Haskell, но я никогда не был очень доволен этим - (я думаю, что это имеет отрицательный оттенок "goto" в моем уме). Я начал изучать Haskell с LYAH, и именно там я взял тенденцию использовать acc и step при написании складок. Где же Конвенция для написания go откуда?

самое главное, что именно это название go должно означать?

3 73

3 ответа:

Мда! Немного археологии!

примерно с 2004 года я использовал go как общее имя для хвостовых рекурсивных рабочих циклов, при выполнении преобразования worker/wrapper рекурсивной функции. Я начал использовать его широко в 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 года.

это было написано в RWH, и, вероятно, был популяризирован оттуда. Кроме того,в потоке слияния библиотека, Дункан Куттс и я начал много этим заниматься.

из источников GHC

идиома идет дальше, хотя. foldr в GHC.База дано:

foldr k z = go
      where
         go []     = z
         go (y:ys) = y `k` go ys

который, вероятно, где я взял трюк (я думал, что это было из тезиса Энди Гилла, но не могу найти никакого использования go есть). Это не дано в этой форме в Gofer, поэтому я думаю, что это впервые появилось в базе кода GHC.

К 2001 Году, Саймон Марлоу использовал 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 и Глазго

выкапывая старые версии 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. Копаться в реализации "числовые.lhs" однако мы обнаруживаем, что это не то же самое, что версия, которая была добавлена в GHC 2.06 в 1997 году, и очень интересный Патч от Sigbjorne Finne появляется в апреле 1998 года,добавлять go цикл до числового.lhs.

этот говорит, что по крайней мере к 1998 году Сигбьерн добавлял go петли к библиотеке GHC "std", в то время как одновременно, многие модули в ядре компилятора GHC С go петли. Копать дальше, это очень интересная фиксация от Will Partain в июле 1996 года добавляет цикл " go " в GHC -- код исходит от Саймона PJ, хотя!

поэтому я буду называть это как идиома Глазго изобретенный людьми в Глазго, которые работали на GHC в середине 90-х, например Саймон Марлоу,Sigbjorn Финне,Будет Partain и Саймон Пейтон Джонс.

очевидно, что ответ не является правильным. Позвольте мне просто добавить небольшую деталь (поскольку, похоже, это мое письмо, на которое вы прямо ссылаетесь): go-это хорошо, потому что это всего две буквы.

О, и причина, по которой книга Yesod посвящает так много контента пакету enumerator, заключается в том, что я уже написал трехчастный учебник enumerator как серию сообщений в блоге, поэтому решил, что я могу также включить его в Книгу. Пакет перечислителя используется в нескольких местах во всем Есод, так что это актуально.

интересно, как часто go паттерн соответствует параметрам накопления и, в более общем плане, стратегиям продолжения кодирования, которые Митч Уонд исследовал в статье Стратегии Преобразования Программы На Основе Продолжения (одна из моих самых любимых статей). В этих случаях!--0--> функция имеет особое значение, которое затем может быть использовано для получения эффективного кода из элегантной спецификации.