haskell - How define an average function when dealing with monads -


i have list of type

primmonad m => m [double] 

to calculate average defined following functions:

sum' :: primmonad m => m [double] -> m double sum' xs = (sum <$> xs)  len' :: primmonad m => m [double] -> m int len' xs = length <$> xs  avg :: primmonad m => m [double] -> m double avg xs = (sum' xs) / (fromintegral $ len' xs) 

however, having problems avg function. following errors:

    not deduce (fractional (m double)) arising use of ‘/’ …                                                                                                    context (primmonad m)                                                                                                                                                                                     bound type signature                                                                                                                                                                                             avg :: primmonad m => m [double] -> m double                                                                                                                                                          @                                                                                                                                        in expression: (sum' xs) / (fromintegral $ len' xs)                                                                                                                                                          in equation ‘avg’:                                                                                                                                                                                            avg xs = (sum' xs) / (fromintegral $ len' xs)                                                                                                                                                          not deduce (integral (m int)) …                                                                                                                                     arising use of ‘fromintegral’                                                                                                                                                                           context (primmonad m)                                                                                                                                                                                     bound type signature                                                                                                                                                                                             avg :: primmonad m => m [double] -> m double                                                                                                                                                          @                                                                                                                                        in expression: fromintegral                                                                                                                                                                                  in second argument of ‘(/)’, namely ‘(fromintegral $ len' xs)’                                                                                                                                               in expression: (sum' xs) / (fromintegral $ len' xs)                                                                                                                                                      compilation failed. 

what need simple function defined?

the problem lies on / wanting number double, not number inside monad m double.

a naive fix be

avg :: primmonad m => m [double] -> m double avg xs = (/) <$> sum' xs <*> (fromintegral <$> len' xs) 

but unsatisfactory, since run monadic action xs twice.

i'd rather use like

avg :: primmonad m => m [double] -> m double avg xs = (\ys -> sum ys / fromintegral (length ys)) <$> xs 

i avoid naming xs monadic action, since xs can taken plain list. matter of personal preference.

even better, i'd define non-monadic average first:

avg :: [double] -> double avg xs = sum xs / fromintegral (length xs)  avgm :: primmonad m => m [double] -> m double avgm = fmap avg 

since avgm short, omit definition, , directly call fmap avg needed.


Comments

Popular posts from this blog

ios - RestKit 0.20 — CoreData: error: Failed to call designated initializer on NSManagedObject class (again) -

laravel - PDOException in Connector.php line 55: SQLSTATE[HY000] [1045] Access denied for user 'root'@'localhost' (using password: YES) -

java - Digest auth with Spring Security using javaconfig -