0

在尝试学习一些 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

但这不仅看起来多余,而且也不起作用。

任何提示表示赞赏!

4

1 回答 1

3

Try this:

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

mzero is the "nothing" or (indeed) "zero" value, which you can use here to model the absence of a result. It has type m x for any type x and monad with zero m, so it fits here.

Instead, return wraps any value in any monad. In particular, you can insert our (a,[a]) pair inside m. (This does not even require the monad to be a MonadPlus)

Note how in the code above we did not mention any specific monad: the code is indeed generic, so that it can work with any MonadPlus.

Lastly, I used null instead of length ... > 0 since null only examines the first constructor in the list, while length ... > 0 has to traverse it all.

You can actually remove the check by switching to pattern matching:

head' :: MonadPlus m => [a] -> m (a,[a])
head' []     = mzero
head' (x:xs) = return (x, xs)
于 2015-01-11T17:41:23.670 回答