content: -- MEDIAN ---------------------------------------------------------------------
  
  -- median :: [Num] -> Num
  on median(xs)
      -- nth :: [Num] -> Int -> Maybe Num
      script nth
          on |λ|(xxs, n)
              if length of xxs > 0 then
                  set {x, xs} to uncons(xxs)
  
                  script belowX
                      on |λ|(y)
                          y < x
                      end |λ|
                  end script
  
                  set {ys, zs} to partition(belowX, xs)
                  set k to length of ys
                  if k = n then
                      x
                  else
                      if k > n then
                          |λ|(ys, n)
                      else
                          |λ|(zs, n - k - 1)
                      end if
                  end if
              else
                  missing value
              end if
          end |λ|
      end script
  
      set n to length of xs
      if n > 0 then
          tell nth
              if n mod 2 = 0 then
                  (|λ|(xs, n div 2) + |λ|(xs, (n div 2) - 1)) / 2
              else
                  |λ|(xs, n div 2)
              end if
          end tell
      else
          missing value
      end if
  end median
  
  -- TEST -----------------------------------------------------------------------
  on run
  
      map(median, [¬
          [], ¬
          [5, 3, 4], ¬
          [5, 4, 2, 3], ¬
          [3, 4, 1, -8.4, 7.2, 4, 1, 1.2]])
  
      --> {missing value, 4, 3.5, 2.1}
  end run
  
  -- GENERIC FUNCTIONS ----------------------------------------------------------
  
  -- map :: (a -> b) -> [a] -> [b]
  on map(f, xs)
      tell mReturn(f)
          set lng to length of xs
          set lst to {}
          repeat with i from 1 to lng
              set end of lst to |λ|(item i of xs, i, xs)
          end repeat
          return lst
      end tell
  end map
  
  -- Lift 2nd class handler function into 1st class script wrapper
  -- mReturn :: Handler -> Script
  on mReturn(f)
      if class of f is script then
          f
      else
          script
              property |λ| : f
          end script
      end if
  end mReturn
  
  -- partition :: predicate -> List -> (Matches, nonMatches)
  -- partition :: (a -> Bool) -> [a] -> ([a], [a])
  on partition(f, xs)
      tell mReturn(f)
          set lst to {{}, {}}
          repeat with x in xs
              set v to contents of x
              set end of item ((|λ|(v) as integer) + 1) of lst to v
          end repeat
      end tell
      {item 2 of lst, item 1 of lst}
  end partition
  
  -- uncons :: [a] -> Maybe (a, [a])
  on uncons(xs)
      if length of xs > 0 then
          {item 1 of xs, rest of xs}
      else
          missing value
      end if
  end uncons
  