Ну подпись по сути неверна.Результат должен быть Maybe Int
:
main :: Int -> Int -> <b>Maybe Int</b>
main x y = do
first <- compute x y
second <- compute (x+2) (y+2)
third <- compute (x+4) (y+4)
<b>return</b> (first + second + third)
Например, здесь мы return (first + second + third)
, и return
обернет их в Just
конструктор данных.
Этопотому что ваш блок do
неявно использует >>=
из Monad Maybe
, который определен как:
instance Monad Maybe where
Nothing >>=_ = Nothing
(Just x) >>= f = f x
return = Just
Так что это означает, что он действительно "распакует" значения из Just
конструктор данных, но в случае, если из него выйдет Nothing
, это означает, что результатом всего блока do
будет Nothing
.
Это более или менее удобно для Monad Maybe
предложения: вы можете выполнять вычисления в виде цепочки успешных действий, и в случае сбоя одного из них результат будет Nothing
, в противном случае он будет Just result
.
Таким образом, в конце концов вы не можете вернуть Int
вместо Maybe Int
, так как это вполне возможно - с точки зрения типов - что одно или несколько вычислений могут вернуть Nothing
.
Однако вы можете "обработать" результат обработки блока do
, если, например, добавитьзначение «по умолчанию», которое будет использоваться в случае, если одно из вычислений будет Nothing
, например:
import Data.Maybe(fromMaybe)
main :: Int -> Int -> <b>Int</b>
main x y = <b>fromMaybe 0</b> $ do
first <- compute x y
second <- compute (x+2) (y+2)
third <- compute (x+4) (y+4)
return (first + second + third)
Здесь, в случае, если do
-блок, таким образом, возвращает Nothing
, мы его заменяемс 0
(вы, конечно, можете добавить другое значение в fromMaybe :: a -> Maybe a -> a
в качестве значения в случае, если вычисление «провалилось»).
Если вы хотитечтобы вернуть первый элемент в списке Maybe
s, то есть Just
, тогда вы можете использовать asum :: (Foldable t, Alternative f) => t (f a) -> f a
, поэтому вы можете написать свой main
как:
-- first <i>non</i>-failing computation
import Data.Foldable(asum)
import Data.Maybe(fromMaybe)
main :: Int -> Int -> Int
main x y = fromMaybe 0 $ <b>asum</b> [
compute x y
compute (x+2) (y+2)
compute (x+4) (y+4)
]
Обратите внимание, что asum
может по-прежнему содержать только Nothing
с, поэтому вам все равно нужно выполнить некоторую постобработку.