Calculating Maclaurin series for sin(x) I'm very new to Haskell as was hoping to get some feedback on my code AND I have some specific questions. I've posted code below or you can see it here.

I'd welcome ideas on how better to calculate the Maclaurin series. Ideas on how better to do the math itself are welcome but I had in mind what Haskell ideas am I missing out on.

My specific questions are:


Are (almost) all the calculations for Factorial going to be done every time for each value of my Maclaurin series? Or is there some sort of caching going on? One can appreciate that calculating 100! from scratch seems crazy if you've just done 99! 
Notice the signature at end: maclaurin :: ( Floating b) =&gt; Int-&gt; b -&gt; b I tried using maclaurin :: ( Integral a, Floating b) =&gt; a-&gt; b -&gt; b , thinking that would be best. Didn't work. I stumbled on this scheme by removing signature and typing :t maclaurin in WinGHci. I'm surprised it worked! I thought we had to declare each parameter? 




--import Data.List(genericTake)

 -- MacClaurin series for Sin(x) is f(0) + f'(0)(x)/1! + f''(0)(x)^2 / 2!  + 
  ... + f^n (0) x^n / n!
  -- or in the case of Sin(x):  0 + 1x + 0 + -1x^3 / 3! + 0 + 1 x^5 / 5! + 0 
  + -1x^7/7! ...
   -- See Wikipedia https://en.wikipedia.org/wiki/Taylor_series




-- return list of alterating 0 and 1
    -- not needed for maclaurin or macResult
ymod2 :: Integral a =&gt;  [a]
ymod2  = map (\y-&gt;(y `mod` 2)) [0..]    

factorial :: (Integral a) =&gt; a -&gt; a  
factorial 0 = 1  
factorial n = n * factorial (n - 1)



powersMac :: (Integral a) =&gt; a -&gt; a
powersMac n
    | n == 0 = 0
    | n == 1 = 1
    | ( (n `mod` 2) == 0 ) = 0
    | otherwise =  ( (-1) * powersMac (n-2) )

-- return list of 0, 1, 0, -1, 0, 1, 0, -1 ...
powersMacList :: (Integral a) =&gt; [a]
powersMacList  = map (\y-&gt;(powersMac y)) [0..]


-- return list of x^0, x^1, x^2, ... x^n
powersOfx :: (Enum b, Floating b) =&gt;  b -&gt; [b]
powersOfx  x = map (\y-&gt;(x^^y)) [0..]

-- return list of 0, 1, 0, -1, 0, ... to n 
firstLst :: Integral a =&gt;  [a]
firstLst   = zipWith (*) (ymod2 ) (powersMacList)

-- return list of 0x, 1x, 0x^2, -1x^3, ... to n
secondLst :: (Enum b, Floating b) =&gt;  b -&gt; [b]
secondLst  x = zipWith (*) (map fromIntegral(powersMacList )) (powersOfx  x)

-- return list of 0, 1x, 0 , -1x^3 / 3! , 0 , 1 x^5 / 5! , 0 ... to n
thirdLst :: ( Enum b, Floating b) =&gt;  b -&gt; [b]
thirdLst  x = zipWith (/) (secondLst  x) (map fromIntegral ( (map(\y-&gt;(factorial y) ) [0..])) )

-- sum the list to get result
macResult :: (  Enum b, Floating b) =&gt;  Int -&gt; b -&gt; b
macResult  n x = sum (take n (thirdLst  x))

maclaurin :: (  Floating b) =&gt; Int-&gt; b -&gt; b
maclaurin  n x = sum ( take n (zipWith (*) (map(\y-&gt;(x^^y))[0..])(zipWith (/) (map fromIntegral (powersMacList )) (map fromIntegral (map(\y-&gt;(factorial y) )[0..]) )) ))
There's a few builtins you may have missed:

ymod2 = cycle [0,1]


If I read powersMac correctly, it basically goes along [0, 1, 0, -1] in cycles as well. So you can reformulate it as:

powersMac n = [0, 1, 0, -1] !! (n `mod` 4)


Considering that you only directly use it as powersMacList, we can again reformulate with cycle:

powersMacList = cycle [0, 1, 0, -1]


BTW: While we're on these two methods:

map (\y -&gt; f y)


is equivalent to:

map f


Noticing that we can rewrite powersOfx as:

powersOfx = map (x^^) [0..]


firstLst does nothing. When there's a 0 in the one list, there's always a 0 in the other list as well.

The formatting in secondLst is somewhat confusing and difficult to read. Consider:

secondLst x = zipWith (*) (map fromIntegral powersMacList) (powersOfx x)


When you use factorial and run a map factorial [0..] you actually want the list of factorials. I'm stealing this excellent SO answer:

factorials = 1 : zipWith (*) factorials [1..]


which turns thirdList into:

thirdList x = zipWith (/) (secondLst x) factorials


applying everything we learned to maclaurin after discarding the fromIntegral calls (that are most likely a result of overspecific type signatures):

maclaurin n x = sum (take n (zipWith (*) (map (x^^) [0..]) (zipWith (/) powersMacList factorial)


Now putting it all together again, after giving out a bit more generous names than firstLst, secondLst and thirdLst:

factorials = 1 : zipWith (*) factorials [1..]

sinZeroDerivations = cycle [0,1,0,-1]
macRawElements x = zipWith (*) sinZeroDerivations (map (x^^) [0..])
macDiscounted x = zipWith (*) (macRawElements x) factorials

macResult n x = sum (take n (macDiscounted x))


Now if you wanted to be less maintainable you could inline the definitions again, but that's not really necessary, is it?

There's something about macDiscounted that annoys me a bit, namely that it only passes x through to macRawElements. We can fix that by swapping those two around like:

sinMacFactors = zipWith (/) sinZeroDerivations factorials


That allows us to specify a bit cleaner what we want:

macResult n x = sum (zipWith (*) (take n (map (x^^) [0..])) sinMacFactors)


notice the second argument to zipWith. That wants to be written as:

macResult n x = sum (zipWith (*) (map (x^^) [0..n]) sinMacFactors)