Лучший способ решить эту проблему, чтобы создать список ваших полномочий 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
Теперь, вы можете также использовать складку, которая в основном просто чистый цикл, где функция ваше тело цикла, начальное значение, а начальное состояние, и этот список вы предоставите это значения, которые вы зацикливаете. В этом случае ваше состояние - это сумма и сила, на которой вы находитесь. Мы могли бы сделать наш собственный тип данных, чтобы представить это, или мы могли бы просто использовать кортеж с первым элементом является текущим общим и вторым элементом является силой тока:
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]
Ваша функция не использует состояние, но если это так, вы можете использовать 'Data.Foldable', который предоставляет' foldlM :: (Foldable t, Monad m) => (b -> a -> mb) -> b -> ta -> mb'. В стороне, время выполнения вашей функции очень плохое. – user2407038