// TypeScript
function longestPalindrome(s: string): string {
    const expandAroundCenter = (l: number, r: number): number => {
        while (l >= 0 && r <= s.length && s[l] === s[r]) {
            l--;
            r++;
        }
        return r - l - 1;
    };

    let l = 0;
    let r = 0;

    for (let i = 0; i < s.length; i++) {
        const odd  = expandAroundCenter(i, i);
        const even = expandAroundCenter(i, i + 1);

        const max = Math.max(odd, even);
        if (max > r - l + 1) {
            l = i - Math.floor((max - 1) / 2);
            r = i + Math.floor(max / 2);
        }
    }

    return s.substring(l, r + 1);
};

-- Haskell
longestPalindrome :: [] Char -> [] Char
longestPalindrome "" = ""
longestPalindrome s  =
    go 0 0 0
  where
    n = length s

    expandAroundCenter :: Int -> Int -> Int
    expandAroundCenter l r =
        if (l > 0) && (r < n) && (s !! l == s !! r)
        then go (l - 1) (r + 1)
        else r - l - 1

    go :: Int -> Int -> Int -> [] Char
    go i bestStart bestLen
      | i >= n    = take bestLen (drop bestStart s)
      | otherwise =
        let oddLength  = expandAroundCenter s i i
            evenLength = expandAroundCenter s i (i + 1)
            len        = max oddLength evenLength
            (bestStart', bestLen')
              | len > bestLen   =
                  let start = i - (len - 1) `div` 2
                  in (start, len)
              | otherwise       = (bestStart, bestLen)
        in go (i + 1) bestStart' bestLen'