[haskell] Haskell : 왜 도우미 함수의 이름을 “go”로 지정하는 규칙이 있습니까?

내가 볼 go하스켈 재료 나 소스를 읽을 때 많은,하지만 난 그것에 대해 정말 편안 적이 없습니다 – (나는 내 마음에 “고토”의 부정적인 내포를 가지고 추측). 나는 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 #-}

출신 bytestring2005 년 8 월.

이것은 RWH로 작성 되었고 아마도 거기에서 대중화되었을 것입니다. 또한 스트림 퓨전 라이브러리에서 Duncan Coutts와 저는 많은 일을 시작했습니다.

GHC 소스에서

관용구는 더 멀리 돌아갑니다. foldrGHC에서 Base 는 다음과 같이 제공됩니다.

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

아마도 내가 트릭을 집어 들었던 곳일 것입니다 (나는 이것이 Andy Gill의 논문에서 나온 것이라고 생각했지만 go거기에서 어떤 용도도 찾을 수 없습니다 ). 그것은 하지 않습니다 나는이 처음 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정의에있는 showInt1996-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에 추가 된 버전과 동일하지 않으며 Sigbjorne Finne의 매우 흥미로운 패치가 1998 년 4 월에 나타납니다 . goNumeric.lhs로 루프합니다.

이는 1998 년 적어도 Sigbjorne가 추가 것을 말한다 go동시에, 많은 동안 GHC에 루프하는, 라이브러리를 “STD” GHC 컴파일러 코어 모듈은go루프를. 더 자세히 살펴보면 1996 년 7 월 Will Partain 의이 매우 흥미로운 커밋은 GHC에 “go”루프를 추가합니다 . 코드는 Simon PJ에서 가져온 것입니다!

그래서 저는 이것을 글래스고의 사람들이 발명 한 글래스고 관용구 라고 부를 것입니다. 그는 Simon Marlow , Sigbjorn Finne , Will Partain , Simon Peyton Jones 와 같이 90 년대 중반 GHC에서 일했습니다 .


답변

당연히 Don의 대답이 맞습니다. (당신이 직접 언급하고있는 제 글인 것 같기 때문에) 약간의 세부 사항을 추가하겠습니다. go는 두 글자 밖에 없기 때문에 좋습니다.

아, 그리고 Yesod 책이 열거 자 패키지에 너무 많은 내용을 바친 이유는 이미 블로그 포스트 시리즈로 열거 자에 대한 3 부로 구성된 자습서를 작성했기 때문에 책에 포함시키는 것이 좋습니다. 열거 자 패키지는 Yesod의 여러 곳에서 사용되므로 관련이 있습니다.


답변

이 관용구는 선형 구조 (따라서 “루프”)뿐만 아니라 분기 (나무와 같은) 구조에도 적용 할 수있을 것으로 기대합니다.

go패턴이 얼마나 자주 축적 매개 변수에 해당 하는지 ,보다 일반적으로 Mitch Wand가 논문 Continuation-Based Program Transformation Strategies (내가 가장 좋아하는 논문 중 하나) 에서 탐색 한 연속 인코딩 전략과 일치 하는지 궁금합니다 . 이 경우 go함수는 특별한 의미를 가지며, 우아한 사양에서 효율적인 코드를 도출하는 데 사용할 수 있습니다.


답변