Related
I am trying to recursively make a list of random numbers that uses the previous value to get the next (so recursion is required instead of map or fold, and also I prefer to make it explicit unless map/foldr makes it ridiculously simple in comparison).
Using a pure PRNG this is very straightforward and idiomatic, in my opinion (puregaussian uses System.Random to generate a normal variate and has type puregaussian :: System.Random.RandomGen t => t -> Double -> Double -> (Double, t)).
purecurse :: System.Random.RandomGen t => t -> Double -> [Double] -> [Double]
purecurse gen current [] = []
purecurse gen current (x:xs) = let (rand, gen2) = puregaussian gen 0 1
next = current + rand
in current:purecurse gen2 next xs
Unfortunately, pure PRNGs don't seem do be as well developed in Haskell as the monadic ones, so I want to do the same thing using a library like random-fu or mwc-probability, and the solutions I found to work are either unidiomatic, not as concise, or both.
Here's a solution using do notation that works, and why I'm not satisfied with it:
import Control.Monad.Primitive
import System.Random.MWC.Probability
recurse :: PrimMonad m => Gen (PrimState m) -> [Double] -> [Double] -> m [Double]
recurse gen history#(current:_) [] = return history
recurse gen history#(current:_) (x:xs) = do
rand <- (sample (normal 0 1) gen)
let next = current + rand
recurse gen (next:history) xs
First of all I would rather use >>= than do notation, but I couldn't find a way of binding the rand variable that has type m Double and then lifting it to get m [Double] at the end case. There doesn't seem to be a lot of documentation (that I could find) or examples on how to do something like that.
I thought maybe it would be necessary to nest the (>>=) operators, but that could make the function extremely complicated or unreadable. If that is the tradeoff, maybe do notation is just cleaner, but I didn't manage to make even that work and would like to know how to.
Second, the function requires the entire list to be passed on at each call, and gives the list back in reverse (and just switching next and history breaks it).
So. I would like to be able to pass the initial state and a list to recurse over that returns a monadic list of values.
The main question I would like help with is: is there a Haskell idiomatic way of writing such a recursion of monadic values resulting in a monadic list that is similar to the structure of a pure function?
The main question I would like help with is: is there a Haskell idiomatic way of writing such a recursion of monadic values resulting in a monadic list that is similar to the structure of a pure function?
You can do it in two steps. Have your recursive function return a list of "monadic actions", then compose / sequence those actions.
Lets consider a simpler but analogous function to yours, for ease of presentation. Instead of randomness lets consider input. The list you recourse over is there for size only (content is ignored) so lets just use an integer.
rc :: Int -> [Double] -> IO [Double]
rc 0 h = return h
rc n h#(cr:_) = do rand <- readLn :: IO Double
let nx = cr + rand
rc (n-1)(nx:h)
Here is a similar alternative that works the way you wants
rc' :: Int -> Double -> IO [Double]
rc' 0 cr = return []
rc' n cr = do rand <- readLn :: IO Double
let nx = cr + rand
xs <- rc' (n-1) nx
return (nx : xs)
And here without do notation
rc'' :: Int -> Double -> IO [Double]
rc'' 0 cr = return []
rc'' n cr = (readLn :: IO Double) >>= (\rand ->
let nx = cr + rand
in (rc'' (n-1) nx) >>= (\xs ->
return (nx : xs)))
In any case, another thing you can do is abstract away pieces of code, rather than have a monolithic presentation.
In each step you require the current value to generate a new one. So a step is a function of type Double -> IO Double. And this is a pretty neat type, fundamental in the world of monads. You can bind values to a step via x >>= step or compose two steps with step1 >=> step2. So lets go with it.
step :: Double -> IO Double
step cr = do rand <- readLn :: IO Double
return (cr + rand)
It's very easy to understand. You 'generate' a number, add the current one and return the result. And you want to do n such steps, so make a list of steps.
steps :: Int -> [Double -> IO Double]
steps n = replicate n step
Now you can choose how to combine them. For instance it would be very natural to fold a list of steps with >=>. You would get this,
runSteps :: Int -> Double -> IO Double
runSteps n = foldr (>=>) return (steps n)
It's close to what you want but only returns the final result, rather than accumulate the generated values at each step. Below is a (restricted) type of (>=>) and the type of the operator (*=>) we want.
(>=>) :: Monad m => (a -> m a) -> (b -> m a) -> a -> m a
(*=>) :: Monad m => (a -> m a) -> (a -> m [a]) -> a -> m [a]
The definition is,
(*=>) :: Monad m => (a -> m a) -> (a -> m [a]) -> a -> m [a]
(*=>) ac uc c = do x <- ac c
xs <- uc x
return (x:xs)
I actually think this encapsulates the bit you didn't particularly like. Now we abstracted it away to this isolated piece of code. Even away from the recursive calls. And finally we just fold to execute the steps.
execSteps :: Int -> Double -> IO [Double]
execSteps n = foldr (*=>) (\x -> return []) (steps n)
This function differs from the original one in the initial input being a Double rather than a [Double]. But this is the type that makes sense. You'd just be passing a single wrapped double in the original function. And it accumulates the elements in the 'right' order as you requested.
is there a Haskell idiomatic way of writing such a recursion of
monadic values resulting in a monadic list that is similar to the
structure of a pure function
Usually, when need apply a monadic values to a pure function, Applicative operator, such as <$>, <*> may be helpful.
In particular, for list construction, it is often apply operator (:) in recursive way to build a list, like
f [] = []
f (x:xs) = x : f xs
in prefix way:
(:) x (f xs)
However, (:) is pure function, not accept monadic value by default, but the good new is, every data type which is instance of Monad, it also be an instance of Applicative. with help of Applicative operator mentioned above, monadic value can be applied to pure function without any change. For example,
(:) <$> (pure x) <*> (pure .f) xs
will return a monadic List instead of pure list.
Return to your question, personally, I think your solution in question is already almost a idiomatic way to do that (since it is simple and readable) except always append next random value at the head of history.
As you said, the list back in reverse and worse, when the history list has old random value already, it is inconvenient to find out which is new add to it.
To solve it, it can be modified slightly as:
recurse :: PrimMonad m => Gen (PrimState m) -> [Double] -> [Double] -> m [Double]
recurse gen history [] = return history
recurse gen history (x:xs) = do rand <- (sample (normal 0 1) gen)
let next = (last history) + rand
recurse gen (history ++ [next]) xs
It make sense, if the last element of history is the newest random value.
However, the different between (:) and (++) is: (:) is O(1), but (++) is O(N), where the N is the length of history list. (and last history is also O(N) instead of O(1)).
To archive an efficient solution, a helper function may need to introduce, say, newHistory, to construct a new list of random value as:
newHistory::PrimMonad m=>Gen(PrimState m)->m Double->[Double]->m [Double]
newHistory _ _ [] = return []
newHistory gen current (x:xs) = let next = (+) <$> current <*> sample (normal 0 1) gen
in (:) <$> next <*> newHistory gen next xs
As said before, with help of Applicative operator, the syntax look like pure function, except apply function in prefix way and use Applicative operator.
And then append back to the original history list as:
(++) <$> pure history <*> newHistory gen (pure $ last history) xs
And the Applicative version of recurse function look like:
recurse2::PrimMonad m=>Gen(PrimState m)->[Double]->[Double]->m [Double]
recurse2 gen history xs =
(++) <$> pure history <*> newHistory gen (pure $ last history) xs
where newHistory::PrimMonad m=>Gen(PrimState m)->m Double->[Double]->m [Double]
newHistory _ _ [] = return []
newHistory gen current (x:xs) =
let next = (+) <$> current <*> sample (normal 0 1) gen
in (:) <$> next <*> newHistory gen next xs
In situations like this, I usually jump straight to using a streaming library with a suitably list-like interface, like streaming. They allow a more natural translation from pure code to monadic, and have the added benefit that you aren't required to construct/consume all of the results at once, but instead incrementally, just as with pure lists.
I'm not sure what purecurse is doing, but it could be written as
import Streaming
import qualified Streaming.Prelude as S
recurse :: PrimMonad m
=> Gen (PrimState m)
-> Double
-> [Double]
-> Stream (Of Double) m ()
recurse gen current [] =
return ()
recurse gen current (x:xs) =
S.yield current *> -- (*>) and (>>) work like concatenation for pure lists
lift (sample (normal 0 1) gen) >>= \rand ->
recurse gen (current + rand) xs
Or, more naturally using do-notation, as:
recurse :: PrimMonad m
=> Gen (PrimState m)
-> Double
-> [Double]
-> Stream (Of Double) m ()
recurse gen current [] =
return ()
recurse gen current (x:xs) =
do S.yield current -- (*>) and (>>) work like concatenation for pure lists
rand <- lift $ sample (normal 0 1) gen
recurse gen (current + rand) xs
Now you can use function like S.take to generate/extract only parts of the result. If you want to get the whole list, you can use S.toList_.
Your issue seems to lie with do-notation and monads. You're assuming there's much more magic going on than there actually is: learning how the desugaring works will help you out here.
Anyway, let's try and convert the non-monadic version into the monadic one step-by-step. First, the type signature:
recurse :: PrimMonad m => Gen (PrimState m) -> Double -> [Double] -> m [Double]
I'm not sure why you had [Double] as the second parameter in your version: we want to change as little as possible from the original. The first clause, then:
purecurse gen current [] = []
-- Goes to:
recurse gen current [] = return []
Again, we're changing as little as possible: no effects were happening in this clause in your pure code, so no effects should be happening here, either. You got the next two lines right:
purecurse gen current (x:xs) = let (rand, gen2) = puregaussian gen 0 1
next = current + rand
-- Goes to:
recurse gen current (x:xs) = do rand <- (sample (normal 0 1) gen)
let next = current + rand
But the last one tripped you up. Ideally, we would write:
in current:purecurse gen2 next xs
-- Goes to:
current:recurse gen next xs
But it doesn't work! What's more, you get a confusing error:
• Couldn't match type ‘Double’ with ‘[Double]’
Expected type: m [Double]
Actual type: [Double]
This is probably what led you down the wrong path. The issue has nothing to do with the lists: it's to do with the m (the encapsulating monad). When you write current : xs, xs has to be a list: in this example, it's actually a m [Double], or a list wrapped in the monad. There's two ways to solve the problem (which are both equivalent). We could unwrap the list, using do notation again:
rest <- recurse gen next xs
return (current : rest)
Or we could lift the function current : to work inside the monad:
fmap (current:) (recurse gen next xs)
let rec (l:int list) f int list =
match l with
| [] -> []
| hd::tl -> 2+tl
I want to know is hd the first element and then tl is the second element because when i do this I keep getting an error, if tl is not the second element how would i access the second element an in depth explanation of hd::tl would be highly appreciated thank you
No tl is not the second element, it is the rest of the list and it has type 'a list. Here hd and tl are just variable names that you choose to bind to the first element of a list, and to the rest of the list (i.e., to a list that contains all elements except the first one). You can choose other names, e.g., fst::rest. Getting the second element, in that case would be as easy as fst::snd::rest (or x::y::rest - again the name doesn't matter).
What you're trying to use is called pattern matching. It is a feature of some languages, that provides a mechanism to easily deconstruct compound data structures. The idea is that if you're deconstructing data structures the same way as you're constructing them, e.g,
let xs = [1;2;3;4]
and here is the deconstructing
let [x1;x2;x3;x4] = xs
In fact, [x;y;...;z] is a syntactic sugar for a more basic syntax x :: y:: ... :: z :: [], so another way to construct the [1;2;3;4] list is to use the following construct: 1::2::3::4::[]. The same works in the opposite direction, e.g.,
let x1::x2::x3::x4::[] = xs
Now we are ready to the next step, what if the structure on the right doesn't match the structure on the left, e.g.,
let [x;y;z] = [1;2]
or
let x::y::z::[] = 1::2::[]
In that case, the matching will fail. In our case in runtime. To prevent this, and to allow programmers to handle all possible configuration of their data structures OCaml provides the match construct in which you specify multiple variants of the value structure, and the first one that matches is chosen, e.g.,
let orcish_length xs = match xs with
| [] -> 0
| x :: [] -> 1
| x :: y :: [] -> 2
| x :: y :: z :: [] -> 3
The function above anticipates only lists that have up to three elements (because Orcs can't count beyond three). But we can. For this we will use the following feature -- if the last element of the list pattern is not [] (that is matches only and only with the empty list, and designates the end-of-list), but anything else (i.e., a variable), then this variable will be bound to all elements, e.g.,
let rec elvish_length xs = match xs with
| [] -> 0
| x :: [] -> 1
| x :: y :: [] -> 2
| x :: y :: z :: [] -> 3
| x :: y :: z :: leftovers -> 3 + elvish_length leftovers
So now, we anticipate all possible list patterns. However, the function is now overcomplicated (because Elves are complicating). Now, let's finally derive a normal, human readable, length function,
let rec length xs = match xs with
| [] -> 0
| x :: xs -> 1 + length xs
As an exercise, try to prove to yourself that this function anticipates all possible lists.
:: is read cons and is an infix version of List.cons. In a functional language like Ocaml, list is a linked list where i.e.[e1; e2; e3; e4] can be reduced to something like this:
cons(::)
/ \
e1 cons(::)
/ \
e2 cons(::)
/ \
e3 cons(::)
/ \
e4 [ ]
Basically, any list can be reduced to a tree of recursive cons expressions, which makes recursion so useful in Ocaml or similar functional languages. At each level, you can reduce a list to its head and its tail, where tail is the list minus its head and can be reduced further until last :: []. So with the above example, you can recursively reduce the list until you find the last element by pattern-matching:
let find_last li =
match li with
| [] -> None (* no element *)
| [last] -> Some last (* found last *)
| head :: tail -> find_last tail (* keep finding *)
;;
Note that [last] can be replaced with last::[] and head::tail with List.cons head tail. What is important is at any point a list can always be reduced to head :: tail, where head is the first element and tail is the list without head.
Pattern-matching is useful in matching the "shape" or state of the reducing list.
I have a list of lists of tuples:
let list = [[(1,(2,2)),(0,(3,2)),(0,(4,2))],[(0,(2,3)),(0,(3,3)),(0,(4,3))],[(0,(2,4)),(0,(3,4)),(0,(4,4))]]
I would like to filter them by the first value of each tuple.
That's what I tried...
compute :: Matrix -> Coordinates -> Matrix
compute m (x,y) = filter (\(a,(_,_)) -> a /= 1) [row | row <- list]
with
type Matrix = [[Int]]
type Coordinates = (Int, Int)
That's the error I got:
ContiguousRegion.hs:20:36:
Couldn't match expected type ‘[Int]’
with actual type ‘(Integer, (t0, t1))’
In the pattern: (a, (_, _))
In the first argument of ‘filter’, namely
‘(\ (a, (_, _)) -> a /= 1)’
In the expression:
filter
(\ (a, (_, _)) -> a /= 1) [row | row <- checkAround m (x, y)]
ContiguousRegion.hs:20:58:
Couldn't match type ‘(Int, (Int, Int))’ with ‘Int’
Expected type: [Int]
Actual type: [(Int, (Int, Int))]
In the expression: row
In the second argument of ‘filter’, namely
‘[row | row <- checkAround m (x, y)]’
Failed, modules loaded: none.
How can I solve this?
Thanks!
Let's take a few steps to simplify the compute function and figure out the problem:
First of all, [row | row <- list] does nothing, it's equivalent to just list, so we can remove it and replace it with list, to make the function easier to read:
compute m (x,y) = filter (\(a,(_,_)) -> a /= 1) list
By the way, in your message I see that list isn't what the argument to filter is actually called. Instead, it's a checkAround m (x, y), so compute should probably look like this:
compute m (x,y) = filter (\(a,(_,_)) -> a /= 1) $ checkAround m (x, y)
The function you're passing to filter is unnecessarily complicated, we can replace it with \(a,_) -> a /= 1 or even (/=1) . fst to make it less noisy. Doing that gives us:
compute m (x,y) = filter ((/=1) . fst) list
I'd say it's now much easier to see the problem. Your list has the type [[(Int, (Int, Int))]], ie. it's a list of lists of tuples.
But the predicate your passing into filter is expecting a tuple, therefore filter itself is expecting a list of tuples.
This is an obvious type mismatch. How do we solve this? I don't know, that's up to you, but I guess you want to filter the inner list.
How do we do this? Well, we need to go through each of the inner lists, filter them and put the filtered ones in a new list. This is exactly what map (or fmap) can help us with. Let's map the filter we've constructed over list:
compute m (x,y) = map (filter ((/=1) . fst)) list
Unfortunately, the above still gives us a type error:
Couldn't match type ‘(Integer, (Integer, Integer))’ with ‘Int’
Expected type: [[Int]]
Actual type: [[(Integer, (Integer, Integer))]]
Well, why is that? We know that the Actual type is the type of list and the type of the filtered list as well, but what is the Expected type and why is it a [[Int]]?
The answer lies in your type signature, Matrix -> Coordinates -> Matrix. compute is supposed to produce a list of lists of Ints, but we're filtering something a bit different.
At this point I don't really know what you'd like to do, so I'll just end here, but I suspect you either need to change compute's type signature or you need to somehow merge m with the filtered results to create a new matrix.
Problem 1: Your definition of compute refers to list, but list is not a parameter.
Problem 2: If you change list to m your code is correct, but the type signature you gave is not correct.
Solution:
Change list to m, and don't give a type a signature:
compute m (x,y) = filter (\(a,(_,_)) -> a /= 1) [row | row <- m]
Now ask ghci what the type signature should be:
ghci> :t compute
compute
:: (Eq a, Num a) => [(a, (t2, t3))] -> (t, t1) -> [(a, (t2, t3))]
Now you see that that type Matrix should be defined as
type Matrix = [ (Int, (Int,Int) ]
Is this what you are trying to do?
type SparseMatrix = [Row]
type Row = [Element]
type Element = (Int, Coordinates)
type Coordinates = (Int, Int)
removeRowVal :: Row -> Int -> Row
removeRowVal row i = filter ((/= i).fst) row
removeSMVal :: SparseMatrix -> Int -> SparseMatrix
removeSMVal sm i = [removeRowVal row i | row <- sm]
Even if your list is not some kind of oddly structured sparse matrix representation, I think the final result is what you described.
For example, I am writing some function for lists and I want to use length function
foo :: [a] -> Bool
foo xs = length xs == 100
How can someone understand could this function be used with infinite lists or not?
Or should I always think about infinite lists and use something like this
foo :: [a] -> Bool
foo xs = length (take 101 xs) == 100
instead of using length directly?
What if haskell would have FiniteList type, so length and foo would be
length :: FiniteList a -> Int
foo :: FiniteList a -> Bool
length traverses the entire list, but to determine if a list has a particular length n you only need to look at the first n elements.
Your idea of using take will work. Alternatively
you can write a lengthIs function like this:
-- assume n >= 0
lengthIs 0 [] = True
lengthIs 0 _ = False
lengthIs n [] = False
lengthIs n (x:xs) = lengthIs (n-1) xs
You can use the same idea to write the lengthIsAtLeast and lengthIsAtMost variants.
On edit: I am primaily responding to the question in your title rather than the specifics of your particular example, (for which ErikR's answer is excellent).
A great many functions (such as length itself) on lists only make sense for finite lists. If the function that you are writing only makes sense for finite lists, make that clear in the documentation (if it isn't obvious). There isn't any way to enforce the restriction since the Halting problem is unsolvable. There simply is no algorithm to determine ahead of time whether or not the comprehension
takeWhile f [1..]
(where f is a predicate on integers) produces a finite or an infinite list.
Nats and laziness strike again:
import Data.List
data Nat = S Nat | Z deriving (Eq)
instance Num Nat where
fromInteger 0 = Z
fromInteger n = S (fromInteger (n - 1))
Z + m = m
S n + m = S (n + m)
lazyLength :: [a] -> Nat
lazyLength = genericLength
main = do
print $ lazyLength [1..] == 100 -- False
print $ lazyLength [1..100] == 100 -- True
ErikR and John Coleman have already answered the main parts of your question, however I'd like to point out something in addition:
It's best to write your functions in a way that they simply don't depend on the finiteness or infinity of their inputs — sometimes it's impossible but a lot of the time it's just a matter of redesign. For example instead of computing the average of the entire list, you can compute a running average, which is itself a list; and this list will itself be infinite if the input list is infinite, and finite otherwise.
avg :: [Double] -> [Double]
avg = drop 1 . scanl f 0.0 . zip [0..]
where f avg (n, i) = avg * (dbl n / dbl n') +
i / dbl n' where n' = n+1
dbl = fromInteger
in which case you could average an infinite list, not having to take its length:
*Main> take 10 $ avg [1..]
[1.0,1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0]
In other words, one option is to design as much of your functions to simply not care about the infinity aspect, and delay the (full) evaluation of lists, and other (potentially infinite) data structures, to as late a phase in your program as possible.
This way they will also be more reusable and composable — anything with fewer or more general assumptions about its inputs tends to be more composable; conversely, anything with more or more specific assumptions tends to be less composable and therefore less reusable.
There are a couple different ways to make a finite list type. The first is simply to make lists strict in their spines:
data FList a = Nil | Cons a !(FList a)
Unfortunately, this throws away all efficiency benefits of laziness. Some of these can be recovered by using length-indexed lists instead:
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
data Nat = Z | S Nat deriving (Show, Read, Eq, Ord)
data Vec :: Nat -> * -> * where
Nil :: Vec 'Z a
Cons :: a -> Vec n a -> Vec ('S n) a
instance Functor (Vec n) where
fmap _f Nil = Nil
fmap f (Cons x xs) = Cons (f x) (fmap f xs)
data FList :: * -> * where
FList :: Vec n a -> FList a
instance Functor FList where
fmap f (FList xs) = FList (fmap f xs)
fcons :: a -> FList a -> FList a
fcons x (FList xs) = FList (Cons x xs)
funcons :: FList a -> Maybe (a, FList a)
funcons (FList Nil) = Nothing
funcons (FList (Cons x xs)) = Just (x, FList xs)
-- Foldable and Traversable instances are straightforward
-- as well, and in recent GHC versions, Foldable brings
-- along a definition of length.
GHC does not allow infinite types, so there's no way to build an infinite Vec and thus no way to build an infinite FList (1). However, an FList can be transformed and consumed somewhat lazily, with the cache and garbage collection benefits that entails.
(1) Note that the type system forces fcons to be strict in its FList argument, so any attempt to tie a knot with FList will bottom out.
I have a simple function (used for some problems of project Euler, in fact). It turns a list of digits into a decimal number.
fromDigits :: [Int] -> Integer
fromDigits [x] = toInteger x
fromDigits (x:xs) = (toInteger x) * 10 ^ length xs + fromDigits xs
I realized that the type [Int] is not ideal. fromDigits should be able to take other inputs like e.g. sequences, maybe even foldables ...
My first idea was to replace the above code with sort of a "fold with state". What is the correct (= minimal) Haskell-category for the above function?
First, folding is already about carrying some state around. Foldable is precisely what you're looking for, there is no need for State or other monads.
Second, it'd be more natural to have the base case defined on empty lists and then the case for non-empty lists. The way it is now, the function is undefined on empty lists (while it'd be perfectly valid). And notice that [x] is just a shorthand for x : [].
In the current form the function would be almost expressible using foldr. However within foldl the list or its parts aren't available, so you can't compute length xs. (Computing length xs at every step also makes the whole function unnecessarily O(n^2).) But this can be easily avoided, if you re-thing the procedure to consume the list the other way around. The new structure of the function could look like this:
fromDigits' :: [Int] -> Integer
fromDigits' = f 0
where
f s [] = s
f s (x:xs) = f (s + ...) xs
After that, try using foldl to express f and finally replace it with Foldable.foldl.
You should avoid the use of length and write your function using foldl (or foldl'):
fromDigits :: [Int] -> Integer
fromDigits ds = foldl (\s d -> s*10 + (fromIntegral d)) 0 ds
From this a generalization to any Foldable should be clear.
A better way to solve this is to build up a list of your powers of 10. This is quite simple using iterate:
powersOf :: Num a => a -> [a]
powersOf n = iterate (*n) 1
Then you just need to multiply these powers of 10 by their respective values in the list of digits. This is easily accomplished with zipWith (*), but you have to make sure it's in the right order first. This basically just means that you should re-order your digits so that they're in descending order of magnitude instead of ascending:
zipWith (*) (powersOf 10) $ reverse xs
But we want it to return an Integer, not Int, so let's through a map fromIntegral in there
zipWith (*) (powersOf 10) $ map fromIntegral $ reverse xs
And all that's left is to sum them up
fromDigits :: [Int] -> Integer
fromDigits xs = sum $ zipWith (*) (powersOf 10) $ map fromIntegral $ reverse xs
Or for the point-free fans
fromDigits = sum . zipWith (*) (powersOf 10) . map fromIntegral . reverse
Now, you can also use a fold, which is basically just a pure for loop where the function is your loop body, the initial value is, well, the initial state, and the list you provide it is the values you're looping over. In this case, your state is a sum and what power you're on. We could make our own data type to represent this, or we could just use a tuple with the first element being the current total and the second element being the current power:
fromDigits xs = fst $ foldr go (0, 1) xs
where
go digit (s, power) = (s + digit * power, power * 10)
This is roughly equivalent to the Python code
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]
Such a simple function can carry all its state in its bare arguments. Carry around an accumulator argument, and the operation becomes trivial.
fromDigits :: [Int] -> Integer
fromDigits xs = fromDigitsA xs 0 # 0 is the current accumulator value
fromDigitsA [] acc = acc
fromDigitsA (x:xs) acc = fromDigitsA xs (acc * 10 + toInteger x)
If you're really determined to use a right fold for this, you can combine calculating length xs with the calculation like this (taking the liberty of defining fromDigits [] = 0):
fromDigits xn = let (x, _) = fromDigits' xn in x where
fromDigits' [] = (0, 0)
fromDigits' (x:xn) = (toInteger x * 10 ^ l + y, l + 1) where
(y, l) = fromDigits' xn
Now it should be obvious that this is equivalent to
fromDigits xn = fst $ foldr (\ x (y, l) -> (toInteger x * 10^l + y, l + 1)) (0, 0) xn
The pattern of adding an extra component or result to your accumulator, and discarding it once the fold returns, is a very general one when you're re-writing recursive functions using folds.
Having said that, a foldr with a function that is always strict in its second parameter is a really, really bad idea (excessive stack usage, maybe a stack overflow on long lists) and you really should write fromDigits as a foldl as some of the other answers have suggested.
If you want to "fold with state", probably Traversable is the abstraction you're looking for. One of the methods defined in Traversable class is
traverse :: Applicative f => (a -> f b) -> t a -> f (t b)
Basically, traverse takes a "stateful function" of type a -> f b and applies it to every function in the container t a, resulting in a container f (t b). Here, f can be State, and you can use traverse with function of type Int -> State Integer (). It would build an useless data structure (list of units in your case), but you can just discard it. Here's a solution to your problem using Traversable:
import Control.Monad.State
import Data.Traversable
sumDigits :: Traversable t => t Int -> Integer
sumDigits cont = snd $ runState (traverse action cont) 0
where action x = modify ((+ (fromIntegral x)) . (* 10))
test1 = sumDigits [1, 4, 5, 6]
However, if you really don't like building discarded data structure, you can just use Foldable with somewhat tricky Monoid implementation: store not only computed result, but also 10^n, where n is count of digits converted to this value. This additional information gives you an ability to combine two values:
import Data.Foldable
import Data.Monoid
data Digits = Digits
{ value :: Integer
, power :: Integer
}
instance Monoid Digits where
mempty = Digits 0 1
(Digits d1 p1) `mappend` (Digits d2 p2) =
Digits (d1 * p2 + d2) (p1 * p2)
sumDigitsF :: Foldable f => f Int -> Integer
sumDigitsF cont = value $ foldMap (\x -> Digits (fromIntegral x) 10) cont
test2 = sumDigitsF [0, 4, 5, 0, 3]
I'd stick with first implementation. Although it builds unnecessary data structure, it's shorter and simpler to understand (as far as a reader understands Traversable).