Это логично.Компилятор отображает значение типа a
, но здесь вы не можете указать никакого значения, поскольку a
может быть любым (a Bool
, Int
, [Int]
, Maybe Int
и т. Д.).
Это не столько проблема программирования, сколько проблема design : что вы хотите сделать, если это Nothing
?Здесь есть несколько вариантов:
с предоставлением значения по умолчанию, поэтому сигнатура будет:
fUnwrap :: <b>a -></b> Maybe a -> a
fUnwrap <b>_</b> (Just n) = n
fUnwrap <b>d</b> Nothing = <b>d</b>
, в случае ошибкиэто Nothing
(мы можем сделать это, либо оставив строку, либо явно выдав ошибку, хотя в последнем случае мы можем указать причину):
fUnwrap :: Maybe a -> a
fUnwrap (Just n) = n
fUnwrap Nothing = <b>error "Nothing has no value"</b>
мы возвращаем undefined
:
fUnwrap :: Maybe a -> a
fUnwrap (Just n) = n
fUnwrap Nothing = <b>undefined</b>
undefined :: a
- это объект, который выдает ошибку, если его оценивают.Таким образом, это особый случай error
, но мы «откладываем» оценку так, что если значение не является необходимым, мы не получаем ошибку.
Но лично я думаю, чтоПервый подход здесь целесообразен, так как сигнатуры функций не указывают, что они могут вызвать ошибку, таким образом, это приводит к тому, что код может завершиться сбоем, не имея намека на это.
A Maybe a
обычно используется кактип результата вычисления, который может "потерпеть неудачу": в случае успеха он возвращает Just x
(с x
результатом), а в противном случае возвращает Nothing
.
Вы можете использовать, например,do
нотация для построения Maybe a
из цепочки вычислений, которые могут потерпеть неудачу.Например:
foo :: Int -> Maybe Int
foo x = do
y <- someComputation x
otherComputation y
с приведенным здесь примером someComputation, otherComputation :: Int -> Maybe Int
.