使用MonadPlus处理错误

时间:2015-01-11 17:11:37

标签: haskell monads

在尝试学习一些Haskell时再次陷入困境。我想要做的是为具有错误处理的列表实现组合head/tail方法。签名必须如下所示:

head' :: MonadPlus m => [a] -> m (a,[a])

但是我对MonadPlus的错误处理方式有点迷失。我尝试了以下方法:

head' xs = if (length xs > 0) then Just(head xs, tail xs) else Nothing

但它抱怨:预期类型:m(a,[a])实际类型:可能(a,[a])。为了好玩,我也尝试过:

head' xs = if (length xs > 0) then Just(head xs, tail xs) else Nothing `mplus` Nothing

但这不仅看起来多余,而且也无效。

任何提示都赞赏!

1 个答案:

答案 0 :(得分:3)

试试这个:

head' :: MonadPlus m => [a] -> m (a,[a])
head' xs = if null xs then mzero then return (head xs, tail xs)

mzero是“无”或“确实”为“零”的值,您可以在此处使用该值来模拟结果的缺失。对于任何类型m x,其类型为x,而m为零,因此它适合此处。

相反,return会在任何monad中包含任何值。特别是,您可以在(a,[a])内插入m对。 (这甚至不要求monad是MonadPlus

请注意,在上面的代码中我们没有提到任何特定的monad:代码确实是通用的,因此它可以与任何MonadPlus一起使用。

最后,我使用了null而不是length ... > 0,因为null只检查列表中的第一个构造函数,而length ... > 0必须遍历所有构造函数。

您实际上可以通过切换到模式匹配来删除检查:

head' :: MonadPlus m => [a] -> m (a,[a])
head' []     = mzero
head' (x:xs) = return (x, xs)