Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Restricting type parameter to Monoid

I've previously defined a function which takes a list of Maybes and turns it into a Maybe of a list, like so:

floop :: [Maybe a] -> Maybe [a]
floop [] = Just []
floop (Nothing:_) = Nothing
floop (Just x:xs) = fmap (x:) $ floop xs

Now I want to redefine it to be compatible with a larger class of containers, not just lists, and I've found that it needs to implement the functions foldr, mappend, mempty, fmap , and pure; so I figure that the following type line would be appropriate:

floop :: (Foldable t, Functor t, Monoid t) => t (Maybe a) -> Maybe (t a)

As (I think) it ensures that those functions are implemented for the given container, however it leads to the following error:

Expecting one more argument to ‘t’
The first argument of ‘Monoid’ should have kind ‘*’,
  but ‘t’ has kind ‘* -> *’
In the type signature for ‘floop'’:
  floop' :: (Foldable t, Functor t, Monoid t) =>
            t (Maybe a) -> Maybe (t a)

After looking into it, I found Monoid's kind is different to that of Functor and Foldable, but I can't see why that would be the case, nor how to correct the error.

For those interested, here's the current implementation:

floop :: (Foldable t, Functor t, Monoid t) => t (Maybe a) -> Maybe (t a)
floop xs = let
                f :: (Foldable t, Functor t, Monoid t) => Maybe a -> Maybe (t a) -> Maybe (t a)
                f Nothing _ = Nothing
                f (Just x) ys = fmap (mappend $ pure x) ys
            in
                foldr f (Just mempty) xs

Note: I have been made aware that this already exists as a builtin function (sequence), but I intend to implement it as a learning exercise.

like image 640
Zoey Hewll Avatar asked Dec 06 '25 06:12

Zoey Hewll


1 Answers

Monoidal applicatives are described by the Alternative class, using (<|>) and empty instead of mappend and mempty:

floop :: (Foldable t, Alternative t) => t (Maybe a) -> Maybe (t a)
floop xs = let
                f :: (Foldable t, Alternative t) => Maybe a -> Maybe (t a) -> Maybe (t a)
                f Nothing _ = Nothing
                f (Just x) ys = fmap ((<|>) $ pure x) ys
            in
                foldr f (Just empty) xs 
like image 200
Lee Avatar answered Dec 07 '25 22:12

Lee



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!