Haskell развернуть Возможно сохранить полиморфизм - PullRequest
0 голосов
/ 20 октября 2018

новичок в Haskell снова здесь.Если я хочу развернуть тип Maybe и хочу сохранить его абстрактным, я бы использовал:

fUnwrap :: Maybe a -> a 
fUnwrap (Just n) = n 
fUnwrap Nothing = ???

Независимо от того, что я делаю с Nothing, компилятор не дает понять, что делать более конкретно.с Nothing ... Вы, ребята, можете мне помочь?

Ответы [ 2 ]

0 голосов
/ 20 октября 2018

Это невозможно, так как ваша функция написана.Так как функция чистая, вы не можете вернуть a, так как ваш единственный ввод - Nothing.

Прелесть Maybe в том, что вам не нужно его «разворачивать».Вы можете использовать функцию fmap для работы с упакованными данными, только если они существуют, и неявным образом ничего не делать в случае Nothing.

0 голосов
/ 20 октября 2018

Это логично.Компилятор отображает значение типа a, но здесь вы не можете указать никакого значения, поскольку a может быть любым (a Bool, Int, [Int], Maybe Int и т. Д.).

Это не столько проблема программирования, сколько проблема design : что вы хотите сделать, если это Nothing?Здесь есть несколько вариантов:

  1. с предоставлением значения по умолчанию, поэтому сигнатура будет:

    fUnwrap :: <b>a -></b> Maybe a -> a 
    fUnwrap <b>_</b> (Just n) = n
    fUnwrap <b>d</b> Nothing = <b>d</b>
  2. , в случае ошибкиэто Nothing (мы можем сделать это, либо оставив строку, либо явно выдав ошибку, хотя в последнем случае мы можем указать причину):

    fUnwrap :: Maybe a -> a
    fUnwrap (Just n) = n
    fUnwrap Nothing = <b>error "Nothing has no value"</b>
  3. мы возвращаем undefined:

    fUnwrap :: Maybe a -> a
    fUnwrap (Just n) = n
    fUnwrap Nothing = <b>undefined</b>

    undefined :: a - это объект, который выдает ошибку, если его оценивают.Таким образом, это особый случай error, но мы «откладываем» оценку так, что если значение не является необходимым, мы не получаем ошибку.

Но лично я думаю, чтоПервый подход здесь целесообразен, так как сигнатуры функций не указывают, что они могут вызвать ошибку, таким образом, это приводит к тому, что код может завершиться сбоем, не имея намека на это.

A Maybe a обычно используется кактип результата вычисления, который может "потерпеть неудачу": в случае успеха он возвращает Just xx результатом), а в противном случае возвращает Nothing.

Вы можете использовать, например,do нотация для построения Maybe a из цепочки вычислений, которые могут потерпеть неудачу.Например:

foo :: Int -> Maybe Int
foo x = do
    y <- someComputation x
    otherComputation y

с приведенным здесь примером someComputation, otherComputation :: Int -> Maybe Int.

...