I found this implementation of the average function:
avg :: [Int] -> Int
avg = div . sum <*> length
How does this work? I looked at the function that was produced as a result of div . sum
:
(div . sum) :: (Integral a, Foldable t) => t a -> a -> a
I understand that, but I'm unable to tell how <*> length
does the work.
Count the number of elements in the rates list: let countRates = length rates. Divide sumRates by countRates . But before you do that, convert countRates to a floating point number. Otherwise Haskell will complain: sumRates / (fromIntegral countRates)
() is very often used as the result of something that has no interesting result. For example, an IO action that is supposed to perform some I/O and terminate without producing a result will typically have type IO () .
The workhorse for converting from integral types is fromIntegral , which will convert from any Integral type into any Num eric type (which includes Int , Integer , Rational , and Double ): fromIntegral :: (Num b, Integral a) => a -> b.
You can calculate the average of the second elements of the list of tuples, you don't need to do the sum yourself because Scala has a builtin function for that. First we need to transform the list of tuples to a list of Int values, we can do that using the map function as shown below. val average = list.
<*> :: Applicative f => f (a -> b) -> f a -> f b
is the sequential application function that works on an Applicative
structure. For a function, this is implemented as [src]:
instance Applicative ((->) r) where pure = const (<*>) f g x = f x (g x) liftA2 q f g x = q (f x) (g x)
so f <*> g
is short for \x -> f x (g x)
. This thus means that in the case of avg
:
avg = div . sum <*> length
is equivalent to:
avg x = (div . sum) x (length x)
which is thus equivalent to:
avg x = div (sum x) (length x)
so it divides the sum x
with length x
.
I'm not a fan of this particular pointfree-trick. It uses the Applicative (a->)
instance as a “fanout”, to pass the argument to two separate functions. Essentially those two functions are sum
and length
, and the results are then combined back by div
, which can be expressed nicely with arrow combinators (albeit a bit more verbose, because arrows don't really play in Haskell's default curried style):
import Control.Arrow
avg = uncurry div . (sum &&& length)
In the applicative trick, you merge the combining function into the first argument-sharing one. So div . sum
in this case, and the result of the other function length
is then passed into the second argument of the first function.
You can also use
avg = liftA2 div sum length
which uses the Applicative
instance too.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With