This question already has answers here:
product of list iteratively
(2 answers)
Closed 6 years ago.
I'm really new to haskell and would like to multiply all numbers in an array. For example.:
Array:
[3,2,4] //3*2*4
Output
24
Thanks, any help is greatly appreciated.
There are a number of ways of doing it in Haskell.
For instance, you could use:
product [3,2,4]
or equivalently
foldr (*) 1 [3,2,4]
or recursively:
prod [] = 1
prod (x : xs) = x * prod xs
Function foldr is the so called list catamorphism. To understand foldr we need to first understand list constructors. In Haskell, [3,2,4] is a syntax sugar for 3 : 2 : 4 : [], where : is list-cons constructor and [] is the empty list. Application foldr f v replaces every occurrence of : in a list by function f and the empty list for v. Its definition is as follows:
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr f v [] = v -- equation 1
foldr f v (x:xs) = f x (foldr f v xs) -- equation 2
As an example, consider foldr (*) 1 [3,2,4]:
foldr (*) 1 [3,2,4] =
3 * (foldr (*) 1 [2,4]) = (by equation 2 of foldr)
3 * (2 * (foldr (*) 1 [4])) = (by equation 2 of foldr)
3 * (2 * (4 * (foldr (*) 1 []))) = (by equation 2 of foldr)
3 * (2 * (4 * 1)) = (by equation 1 of foldr)
= 24
You can do so with a fold function:
foldr (*) 1 [2,3,4]
or...
foldr1 (*) [2,3,4]
The product function is exactly what you're looking for.
It has also the feature that product [] equals 1, as you would expect mathematically speaking.
If you look at its definition, you can see that product is indeed the fold of multiplication (with 1 as neutral element).
Related
Im trying to make some functions and methods for a Haskell type called "Polynomial" which represents a mathematical polynomial. This type is defined as follows:
data Pol = Nil | P Grade Coefficient (Pol) deriving Show
So, for example the polynomial x^3 + 2x^2 + 8 would be represented as
P 3 1 (P 2 2 (P 0 8 Nil))
There is a function called "list2Pol" which should get a lista [Integer] and transform it into a Polynomial, where the index of that list represent the grade of that coefficient. So, for example:
list2Pol [6,1,0,3] = P 3 3 (P 1 1 (P 0 6 Nil)
However, it seems easy to implement without folds, but I would like to know how to implement it by folding, because my code which is down doesnt work
list2Pol :: [Integer] -> Pol
list2Pol [] = Nil
list2Pol l = foldl (\x solResto -> insert (length l) x solResto) Nil l
I would apreciate you to help me!
You can first zip your list with the list [0..] and then use that as the index:
list2Pol l = foldr (\(i,x) rest -> insert i x rest) Nil (zip [0..] l)
Note that in this case you want to use foldr and not foldl and the [] case is redundant, the fold will take care of that case automatically.
I want to rewrite (or upgrade! :) ) my two functions, hist and sort, using fold-functions. But since I am only in the beginning of my Haskell-way, I can't figure out how to do it.
First of all, I have defined Insertion, Table and imported Data.Char:
type Insertion = (Char, Int)
type Table = [Insertion]
import Data.Char
Then I have implemented the following code for hist:
hist :: String -> Table
hist[] = []
hist(x:xs) = sortBy x (hist xs) where
sortBy x [] = [(x,1)]
sortBy x ((y,z):yzs)
| x == y = (y,z+1) : yzs
| otherwise = (y,z) : sortBy x yzs
And this one for sort:
sort :: Ord a => [a] -> [a]
sort [] = []
sort (x:xs) = paste x (sort xs)
paste :: Ord a => a -> [a] -> [a]
paste y [] = [y]
paste y (x:xs)
| x < y = x : paste y xs
| otherwise = y : x : xs
What can I do next? How can I use the fold-functions to implement them?
foldr f z on a list replaces the "cons" of the list (:) with f and the empty list [] with z.
This thus means that for a list like [1,4,2,5], we thus obtain f 1 (f 4 (f 2 (f 5 z))), since [1,4,2,5] is short for 1 : 4 : 2 : 5 : [] or more canonical (:) 1 ((:) 4 ((:) 2 ((:) 5 []))).
The sort function for example can be replaced with a fold function:
sort :: Ord a => [a] -> [a]
sort = foldr paste []
since sort [1,4,2,5] is equivalent to paste 1 (paste 4 (paste 2 (paste 5 []))). Here f thus takes as first parameter an element, and as second parameter the result of calling foldr f z on the rest of the list,
I leave hist as an exercise.
I'm trying to learn coding in Haskell.
I started with an easy example "the product of a list".
product :: [Integer] -> Integer
product [] = 1
product (x:xs) = x * product xs
I finished this quickly.
Another way is the product function in the API. (product List -> product)
I wonder if there is another iterative way to solve my problem?
You can use a fold:
product :: Num a => [a] -> a
product xs = foldl (*) 1 xs
This can also be done strictly with foldl' or foldr, the differences mostly are performance, but since you're just starting out I'll skip that lecture this time.
So what does a fold do? Let's start with the basic definition of foldl:
foldl :: (a -> b -> a) -> a -> [b] -> a
foldl f acc [] = acc
foldl f acc (x:xs) = foldl f (f acc x) xs
What this does is takes a function f :: a -> b -> a which takes an accumulator and an additional value, which is fed to it from the list of values. It iteratively applies this function, generating a new accumulator at each step, until it runs out of values in the list. For (*) it looks something like
> foldl (*) 1 [1, 2, 3, 4]
| foldl (*) (1 * 1) [2, 3, 4] = foldl (*) 1 [2, 3, 4]
| foldl (*) (1 * 2) [3, 4] = foldl (*) 2 [3, 4]
| foldl (*) (2 * 3) [4] = foldl (*) 6 [4]
| foldl (*) (6 * 4) [] = foldl (*) 24 []
| 24
I should add that this isn't exactly how it's performed in memory unless you use foldl', which is the strict version, but it's easier to follow this way.
Well in Haskell we don't have loops so iterative is relative, but here's the "functional iteration approach"
product = foldl' (*) 1
folds are the equivalent of loops in imperative languages. foldl' in particular is tail recursive and strict so it will run in constant space, similar to a loop.
If we were to write it explicitly
product = go 1
where go accum (x:xs) = go (accum * x) xs
go accum _ = accum -- Subtle performances
-- differences with strictness
This is still recursive, but will compile to similar assembly.
I've been working with problems (such as pentagonal numbers) that involve generating a list based on the previous elements in the list. I can't seem to find a built-in function of the form I want. Essentially, I'm looking for a function of the form:
([a] -> a) -> [a] -> [a]
Where ([a] -> a) takes the list so far and yields the next element that should be in the list and a or [a] is the initial list. I tried using iterate to achieve this, but that yields a list of lists, which each successive list having one more element (so to get the 3000th element I have to do (list !! 3000) !! 3000) instead of list !! 3000.
If the recurrence depends on a constant number of previous terms, then you can define the series using standard corecursion, like with the fibonacci sequence:
-- fibs(0) = 1
-- fibs(1) = 1
-- fibs(n+2) = fibs(n) + fibs(n+1)
fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
-- foos(0) = -1
-- foos(1) = 0
-- foos(2) = 1
-- foos(n+3) = foos(n) - 2*foos(n+1) + foos(n+2)
foos = -1 : 0 : 1 : zipWith (+) foos
(zipWith (+)
(map (negate 2 *) (tail foos))
(tail $ tail foos))
Although you can introduce some custom functions to make the syntax a little nicer
(#) = flip drop
infixl 7 #
zipMinus = zipWith (-)
zipPlus = zipWith (+)
-- foos(1) = 0
-- foos(2) = 1
-- foos(n+3) = foos(n) - 2*foos(n+1) + foos(n+2)
foos = -1 : 0 : 1 : ( ( foos # 0 `zipMinus` ((2*) <$> foos # 1) )
`zipPlus` foos # 2 )
However, if the number of terms varies, then you'll need a different approach.
For example, consider p(n), the number of ways in which a given positive integer can be expressed as a sum of positive integers.
p(n) = p(n-1) + p(n-2) - p(n-5) - p(n-7) + p(n-12) + p(n-15) - ...
We can define this more simply as
p(n) = ∑ k ∈ [1,n) q(k) p(n-k)
Where
-- q( i ) | i == (3k^2+5k)/2 = (-1) ^ k
-- | i == (3k^2+7k+2)/2 = (-1) ^ k
-- | otherwise = 0
q = go id 1
where go zs c = zs . zs . (c:) . zs . (c:) $ go ((0:) . zs) (negate c)
ghci> take 15 $ zip [1..] q
[(1,1),(2,1),(3,0),(4,0),(5,-1),(6,0),(7,-1),(8,0),(9,0),(10,0),(11,0),(12,1),
(13,0),(14,0),(15,1)]
Then we could use iterate to define p:
p = map head $ iterate next [1]
where next xs = sum (zipWith (*) q xs) : xs
Note how iterate next creates a series of reversed prefixes of p to make it easy to use q to calculate the next element of p. We then take the head element of each of these reversed prefixes to find p.
ghci> next [1]
[1,1]
ghci> next it
[2,1,1]
ghci> next it
[3,2,1,1]
ghci> next it
[5,3,2,1,1]
ghci> next it
[7,5,3,2,1,1]
ghci> next it
[11,7,5,3,2,1,1]
ghci> next it
[15,11,7,5,3,2,1,1]
ghci> next it
[22,15,11,7,5,3,2,1,1]
Abstracting this out to a pattern, we can get the function you were looking for:
construct :: ([a] -> a) -> [a] -> [a]
construct f = map head . iterate (\as -> f as : as)
p = construct (sum . zipWith (*) q) [1]
Alternately, we could do this in the standard corecursive style if we define a helper function to generate the reversed prefixes of a list:
rInits :: [a] -> [[a]]
rInits = scanl (flip (:)) []
p = 1 : map (sum . zipWith (*) q) (tail $ rInits p)
Consider the following code I wrote:
import Control.Monad
increasing :: Integer -> [Integer]
increasing n
| n == 1 = [1..9]
| otherwise = do let ps = increasing (n - 1)
let last = liftM2 mod ps [10]
let next = liftM2 (*) ps [10]
alternateEndings next last
where alternateEndings xs ys = concat $ zipWith alts xs ys
alts x y = liftM2 (+) [x] [y..9]
Where 'increasing n' should return a list of n-digit numbers whose numbers increase (or stay the same) from left-to-right.
Is there a way to simplify this? The use of 'let' and 'liftM2' everywhere looks ugly to me. I think I'm missing something vital about the list monad, but I can't seem to get rid of them.
Well, as far as liftM functions go, my preferred way to use those is the combinators defined in Control.Applicative. Using those, you'd be able to write last = mod <$> ps <*> [10]. The ap function from Control.Monad does the same thing, but I prefer the infix version.
What (<$>) and (<*>) goes like this: liftM2 turns a function a -> b -> c into a function m a -> m b -> m c. Plain liftM is just (a -> b) -> (m a -> m b), which is the same as fmap and also (<$>).
What happens if you do that to a multi-argument function? It turns something like a -> b -> c -> d into m a -> m (b -> c -> d). This is where ap or (<*>) come in: what they do is turn something like m (a -> b) into m a -> m b. So you can keep stringing it along that way for as many arguments as you like.
That said, Travis Brown is correct that, in this case, it seems you don't really need any of the above. In fact, you can simplify your function a great deal: For instance, both last and next can be written as single-argument functions mapped over the same list, ps, and zipWith is the same as a zip and a map. All of these maps can be combined and pushed down into the alts function. This makes alts a single-argument function, eliminating the zip as well. Finally, the concat can be combined with the map as concatMap or, if preferred, (>>=). Here's what it ends up:
increasing' :: Integer -> [Integer]
increasing' 1 = [1..9]
increasing' n = increasing' (n - 1) >>= alts
where alts x = map ((x * 10) +) [mod x 10..9]
Note that all refactoring I did to get to that version from yours was purely syntactic, only applying transformations that should have no impact on the result of the function. Equational reasoning and referential transparency are nice!
I think what you are trying to do is this:
increasing :: Integer -> [Integer]
increasing 1 = [1..9]
increasing n = do p <- increasing (n - 1)
let last = p `mod` 10
next = p * 10
alt <- [last .. 9]
return $ next + alt
Or, using a "list comprehension", which is just special monad syntax for lists:
increasing2 :: Integer -> [Integer]
increasing2 1 = [1..9]
increasing2 n = [next + alt | p <- increasing (n - 1),
let last = p `mod` 10
next = p * 10,
alt <- [last .. 9]
]
The idea in the list monad is that you use "bind" (<-) to iterate over a list of values, and let to compute a single value based on what you have so far in the current iteration. When you use bind a second time, the iterations are nested from that point on.
It looks very unusual to me to use liftM2 (or <$> and <*>) when one of the arguments is always a singleton list. Why not just use map? The following does the same thing as your code:
increasing :: Integer -> [Integer]
increasing n
| n == 1 = [1..9]
| otherwise = do let ps = increasing (n - 1)
let last = map (flip mod 10) ps
let next = map (10 *) ps
alternateEndings next last
where alternateEndings xs ys = concat $ zipWith alts xs ys
alts x y = map (x +) [y..9]
Here's how I'd write your code:
increasing :: Integer -> [Integer]
increasing 1 = [1..9]
increasing n = let allEndings x = map (10*x +) [x `mod` 10 .. 9]
in concatMap allEndings $ increasing (n - 1)
I arrived at this code as follows. The first thing I did was to use pattern matching instead of guards, since it's clearer here. The next thing I did was to eliminate the liftM2s. They're unnecessary here, because they're always called with one size-one list; in that case, it's the same as calling map. So liftM2 (*) ps [10] is just map (* 10) ps, and similarly for the other call sites. If you want a general replacement for liftM2, though, you can use Control.Applicative's <$> (which is just fmap) and <*> to replace liftMn for any n: liftMn f a b c ... z becomes f <$> a <*> b <*> c <*> ... <*> z. Whether or not it's nicer is a matter of taste; I happen to like it.1 But here, we can eliminate that entirely.
The next place I simplified the original code is the do .... You never actually take advantage of the fact that you're in a do-block, and so that code can become
let ps = increasing (n - 1)
last = map (`mod` 10) ps
next = map (* 10) ps
in alternateEndings next last
From here, arriving at my code essentially involved writing fusing all of your maps together. One of the only remaining calls that wasn't a map was zipWith. But because you effectively have zipWith alts next last, you only work with 10*p and p `mod` 10 at the same time, so we can calculate them in the same function. This leads to
let ps = increasing (n - 1)
in concat $ map alts ps
where alts p = map (10*p +) [y `mod` 10..9]
And this is basically my code: concat $ map ... should always become concatMap (which, incidentally, is =<< in the list monad), we only use ps once so we can fold it in, and I prefer let to where.
1: Technically, this only works for Applicatives, so if you happen to be using a monad which hasn't been made one, <$> is `liftM` and <*> is `ap`. All monads can be made applicative functors, though, and many of them have been.
I think it's cleaner to pass last digit in a separate parameter and use lists.
f a 0 = [[]]
f a n = do x <- [a..9]
k <- f x (n-1)
return (x:k)
num = foldl (\x y -> 10*x + y) 0
increasing = map num . f 1