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
Post a Comment