Лучший способ решить эту проблему — составить список ваших степеней числа 10. Это довольно просто с помощью iterate
:
powersOf :: Num a => a -> [a]
powersOf n = iterate (*n) 1
Затем вам просто нужно умножить эти степени 10 на их соответствующие значения в списке цифр. Это легко сделать с помощью zipWith (*)
, но сначала вы должны убедиться, что они расположены в правильном порядке. В основном это просто означает, что вы должны изменить порядок цифр, чтобы они были в порядке убывания, а не в порядке возрастания:
zipWith (*) (powersOf 10) $ reverse xs
Но мы хотим, чтобы он возвращал Integer
, а не Int
, так что давайте через map fromIntegral
zipWith (*) (powersOf 10) $ map fromIntegral $ reverse xs
И осталось их суммировать
fromDigits :: [Int] -> Integer
fromDigits xs = sum $ zipWith (*) (powersOf 10) $ map fromIntegral $ reverse xs
Или для любителей безточечных
fromDigits = sum . zipWith (*) (powersOf 10) . map fromIntegral . reverse
Теперь вы также можете использовать fold, который в основном представляет собой чистый цикл for, где функция — это ваше тело цикла, начальное значение — это, ну, начальное состояние, а список, который вы предоставляете, — это значения, которые вы перебираете. . В этом случае ваше состояние — это сумма и то, на какой мощности вы находитесь. Мы могли бы создать собственный тип данных для представления этого или просто использовать кортеж, в котором первый элемент представляет собой текущую сумму, а второй элемент — текущую мощность:
fromDigits xs = fst $ foldr go (0, 1) xs
where
go digit (s, power) = (s + digit * power, power * 10)
Это примерно эквивалентно коду Python
def fromDigits(digits):
def go(digit, acc):
s, power = acc
return (s + digit * power, power * 10)
state = (0, 1)
for digit in digits:
state = go(digit, state)
return state[0]
person
bheklilr
schedule
15.10.2014
Data.Foldable
, что обеспечиваетfoldlM :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m b
. Кроме того, время выполнения вашей функции очень плохое. - person user2407038   schedule 15.10.2014