Я хочу написать простую рекурсивную функцию с 3 входными параметрами и 1 выходным параметром:
getLengthOfNumber :: (String, Int, Int) -> Int
getLengthOfNumber (n, i, res)
| isCharDigit(n!!i+1) = getLengthOfNumber (n, i+1, res+1)
| otherwise = res
Почему Hugs выдает ошибку «Экземпляр Num Char, необходимый для определения getLengthOfNumber»?
!!
имеет более высокий приоритет, чем +
, поэтому n!!i+1
анализируется как (n !! i) + 1
, который пытается добавить единицу к элементу строки, что работает, только если Char
является числом. Вместо этого вы должны написать n !! (i+1)
.
Потому что он интерпретирует:
n!!i+1
в качестве:
(n!!i) + 1
Таким образом, он сначала получает i
-й символ строки, а затем пытается добавить к нему 1
. Теперь в Haskell можно определить произвольный числовой тип. Итак, здесь вы мог добавляете этот символ и 1
вместе, но только если этот символ является числом.
Но при этом вышесказанное не сработает даже при фиксации скоб. Вы не указали, когда выполнять итерацию останавливаться: для строки "123"
она в конечном итоге получит последний символ, а затем вызовет ошибку «слишком большой индекс», когда достигнет конца строки. Кроме того, !!
эффективен в отношении нет: ему требуется Ok) для доступа к элементу k, что делает этот алгоритм квадратичным.
Здесь вы можете использовать takeWhile :: (a -> Bool) -> [a] -> [a]
и length :: [a] -> Int
: сначала возьмите самый длинный префикс символа, а затем возьмите длину этого списка, например:
getLengthOfNumber :: String -> Int
getLengthOfNumber = length . takeWhile isCharDigit
@GeorgNatter: что, если ввести "123"
?
Спасибо! n !! (i + 1) исправил мою проблему. Кроме того, функция работает именно так, как мне нужно.