Introduction
In a previous tip, we saw how to calculate convergent series in Python, using the imperative style (iterative). Now let's do this using the functional style with the Haskell programming language.
Background
A list is a fundamental data structure in the Haskell programming language. In this tip, we'll look at some basic operations with this structure, showing how it facilitates performing mathematical calculations involving data sets.
For those who are not familiar with functional programming languages, I suggest to consult the references at the end of text.
Let's look at some examples of constructions:
numbers = [1..10] -- Creates a list of numbers from 1 to 10
numbers = [1..] -- Creates a infinit list of numbers from 1 to beyond
take 10 numbers -- Get the top ten elements from the list
length numbers -- Get the size of the list
numbers !! n -- Get the Nth element out of a list
numbers = [(x ^2) | x <- [1..]] -- Creates a infinit list of squared numbers
tail numbers -- returns the list without the first element
numbers = cycle[1,2] -- creates a circular list from a finite one
zipWith (+) [4,2,5,6] [2,6,2,3] -- joins two lists by applying the function
between the corresponding elements. In this case, the result will be [6,8,7,9]
For a complete reference on operations with lists in Haskell, see https://www.haskell.org/.
Let's look at some examples of convergent series that we will calculate in the script below:
The Euler constant obtained by the Taylor series (reciprocals of factorials):
ℇ = 1/1 + 1/1 + 1/2 + 1/6 + 1/24 + 1/120 + ...
The PI Number obtained by the Leibniz series:
π/4 = 1 - 1/3 + 1/5 - 1/7 + 1/9 - 1/10 + ...
Reciprocal Fibonacci constant:
ψ = 1/1 + 1/1 + 1/2 + 1/3 + 1/5 + 1/8 ...
Sum of Geometric progression :
1 = 0,9 + 0,09 + 0,009 + 0,0009 + 0,00009 + ...
Using the Code
The examples below were developed in Haskell with the IDE Visual Studio Code. with the following extensions:
-- Calculating some sequences and series
-- Language: Haskell
-- 2018, Jose Cintra
-- josecintra@josecintra.com
-- Sequences
facts = 1 : zipWith (*) facts [1..] -- infinite sequence of factorials
fibs = 1 : 1 : zipWith (+) fibs (tail fibs) -- Infinite sequence of Fibonacci numbers
odds = [1,3..] -- infinite sequence of odd numbers
signs = cycle [1,(-1)] -- infinite sequence that alternates the numbers 1 and -1
euler = [(1 / x) | x <- facts] -- Sequence for the Euler constant by the Taylor series
pi_seq = zipWith (*) signs ([(1 / p) | p <- odds]) -- Sequence for the leibniz series
fib_const = [(1 / x) | x <- fibs] -- Sequence for the Reciprocal Fibonacci Constant
gp = [(9 / x) | x <- [(10 ^ x) | x <- [1,2..]]] -- Sequence for Geometric Progression
main = do
-- Sequences
putStr "Sequences and series in Haskell\n\n"
putStr "Factorials sequence = "
print (take 10 facts)
putStr "Fibonacci sequence = "
print (take 10 fibs)
putStr "Odd numbers sequence = "
print (take 10 odds)
-- Series
putStr "\nEuler constant by Taylor series = "
print (sum (take 50 euler))
putStr "PI number by the Leibniz series= "
print ((sum (take 100000 pi_seq)) * 4)
putStr "Reciprocal Fibonacci Constant = "
print (sum (take 100 fib_const) )
putStr "Geometric Progression for the number one = "
print (sum (take 100 gp))
References
Last Words
We have seen that there are several ways to create and manipulate lists in Haskell. Some constructs may be a bit slower than in other languages. Here are some considerations on the performance of these commands:
Thanks for reading! Visit GitHub for more algorithms.