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