code: def test_loop(self):
      def triangle_with_ints(n):
          return hl.experimental.loop(
              lambda f, x, c: hl.if_else(x > 0, f(x - 1, c + x), c),
              hl.tint32,
              n,
              0,
          )
  
      def triangle_with_tuple(n):
          return hl.experimental.loop(
              lambda f, xc: hl.if_else(
                  xc[0] > 0, f((xc[0] - 1, xc[1] + xc[0])), xc[1]
              ),
              hl.tint32,
              (n, 0),
          )
  
      for triangle in [triangle_with_ints, triangle_with_tuple]:
          assert_evals_to(triangle(20), sum(range(21)))
          assert_evals_to(triangle(0), 0)
          assert_evals_to(triangle(-1), 0)
  
      def fails_typecheck(regex, f):
          with self.assertRaisesRegex(TypeError, regex):
              hl.eval(hl.experimental.loop(f, hl.tint32, 1))
  
      fails_typecheck("outside of tail position", lambda f, x: x + f(x))
      fails_typecheck(
          "wrong number of arguments", lambda f, x: f(x, x + 1)
      )
      fails_typecheck(
          "bound value", lambda f, x: hl.bind(lambda x: x, f(x))
      )
      fails_typecheck(
          "branch condition", lambda f, x: hl.if_else(f(x) == 0, x, 1)
      )
      fails_typecheck(
          "Type error", lambda f, x: hl.if_else(x == 0, f("foo"), 1)
      )
  
imports: import numpy
  import hail
  import unittest
  import pytest
  from ..helpers import *
  from hail.utils import new_temp_file
label_desc: Use image node_id 18 for calling the Tests obj's underlying member method code with example usage: obj.test_loop() and returns: hl, hl