将类型参数限制为Monoid

Zoe*_*wll 3 haskell types type-kinds

我之前已经定义了一个函数,它接受一个Maybes 列表并将其转换Maybe为一个列表,如下所示:

floop :: [Maybe a] -> Maybe [a]
floop [] = Just []
floop (Nothing:_) = Nothing
floop (Just x:xs) = fmap (x:) $ floop xs
Run Code Online (Sandbox Code Playgroud)

现在我想重新定义它是一个较大的容器类,不只是名单的兼容,而且我发现,它需要实现的功能foldr,mappend,mempty,fmap,和pure; 所以我认为以下类型行是合适的:

floop :: (Foldable t, Functor t, Monoid t) => t (Maybe a) -> Maybe (t a)
Run Code Online (Sandbox Code Playgroud)

正如(我认为)它确保为给定容器实现这些功能,但是它会导致以下错误:

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)
Run Code Online (Sandbox Code Playgroud)

在调查之后,我发现它Monoid的种类Functor和那种不同Foldable,但我不明白为什么会这样,也不知道如何纠正错误.

对于那些感兴趣的人,这是当前的实现:

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
Run Code Online (Sandbox Code Playgroud)

注意:我已经意识到这已经作为内置函数(sequence)存在,但我打算将其作为一个学习练习来实现.

Lee*_*Lee 9

Monoidal applicatives由Alternative类描述,使用(<|>)empty代替mappendmempty:

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 
Run Code Online (Sandbox Code Playgroud)